2021-09-26 01:53:56 +02:00
|
|
|
|
;;; bytecomp-tests.el --- Tests for bytecomp.el -*- lexical-binding:t -*-
|
2008-11-30 05:57:33 +00:00
|
|
|
|
|
2022-01-01 02:45:51 -05:00
|
|
|
|
;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
|
2008-11-30 05:57:33 +00:00
|
|
|
|
|
2016-09-24 12:53:46 +03:00
|
|
|
|
;; Author: Shigeru Fukaya <shigeru.fukaya@gmail.com>
|
|
|
|
|
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
|
2008-11-30 05:57:33 +00:00
|
|
|
|
;; Created: November 2008
|
|
|
|
|
;; Keywords: internal
|
|
|
|
|
;; Human-Keywords: internal
|
|
|
|
|
|
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
|
|
|
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
|
|
|
|
;; it under the terms of the GNU General Public License as published by
|
|
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
;; (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
2017-09-13 15:52:52 -07:00
|
|
|
|
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
2008-11-30 05:57:33 +00:00
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
2011-02-14 16:21:42 -05:00
|
|
|
|
(require 'ert)
|
2020-11-30 22:42:08 +01:00
|
|
|
|
(require 'ert-x)
|
2017-02-15 21:03:05 +05:30
|
|
|
|
(require 'cl-lib)
|
2019-05-17 11:25:06 +02:00
|
|
|
|
(require 'subr-x)
|
2018-03-26 21:56:33 -04:00
|
|
|
|
(require 'bytecomp)
|
2011-02-14 16:21:42 -05:00
|
|
|
|
|
2008-11-30 05:57:33 +00:00
|
|
|
|
;;; Code:
|
Constprop of lexical variables
Lexical variables bound to a constant value (symbol, number or string)
are substituted at their point of use and the variable then eliminated
if possible. Example:
(let ((x (+ 2 3))) (f x)) => (f 5)
This reduces code size, eliminates stack operations, and enables
further optimisations. The implementation is conservative, and is
strongly curtailed by the presence of variable mutation, conditions
and loops.
* lisp/emacs-lisp/byte-opt.el
(byte-optimize-enable-variable-constprop)
(byte-optimize-warn-eliminated-variable): New constants.
(byte-optimize--lexvars, byte-optimize--vars-outside-condition)
(byte-optimize--vars-outside-loop, byte-optimize--dynamic-vars):
New dynamic variables.
(byte-optimize--substitutable-p, byte-optimize-let-form):
New functions.
(byte-optimize-form-code-walker): Adapt clauses for variable
constprop, and add clauses for 'setq' and 'defvar'.
* test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-test-var)
(bytecomp-test-get-var, bytecomp-test-identity)
(byte-opt-testsuite-arith-data): Add test cases.
2021-02-06 18:34:45 +01:00
|
|
|
|
(defvar bytecomp-test-var nil)
|
|
|
|
|
|
|
|
|
|
(defun bytecomp-test-get-var ()
|
|
|
|
|
bytecomp-test-var)
|
|
|
|
|
|
|
|
|
|
(defun bytecomp-test-identity (x)
|
|
|
|
|
"Identity, but hidden from some optimisations."
|
|
|
|
|
x)
|
|
|
|
|
|
2021-09-22 11:03:30 +02:00
|
|
|
|
(defmacro bytecomp-test-loop (outer1 outer2 inner1 inner2)
|
|
|
|
|
"Exercise constant propagation inside `while' loops.
|
|
|
|
|
OUTER1, OUTER2, INNER1 and INNER2 are forms placed in the outer and
|
|
|
|
|
inner loops respectively."
|
|
|
|
|
`(let ((x 1) (i 3) (res nil))
|
|
|
|
|
(while (> i 0)
|
|
|
|
|
(let ((y 2) (j 2))
|
|
|
|
|
(setq res (cons (list 'outer x y) res))
|
|
|
|
|
(while (> j 0)
|
|
|
|
|
(setq res (cons (list 'inner x y) res))
|
|
|
|
|
,inner1
|
|
|
|
|
,inner2
|
|
|
|
|
(setq j (1- j)))
|
|
|
|
|
,outer1
|
|
|
|
|
,outer2)
|
|
|
|
|
(setq i (1- i)))
|
|
|
|
|
res))
|
|
|
|
|
|
2021-04-09 18:42:12 +02:00
|
|
|
|
(defconst bytecomp-tests--test-cases
|
2008-11-30 05:57:33 +00:00
|
|
|
|
'(
|
|
|
|
|
;; some functional tests
|
|
|
|
|
(let ((a most-positive-fixnum) (b 1) (c 1.0)) (+ a b c))
|
|
|
|
|
(let ((a most-positive-fixnum) (b -2) (c 1.0)) (- a b c))
|
|
|
|
|
(let ((a most-positive-fixnum) (b 2) (c 1.0)) (* a b c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ a b c))
|
|
|
|
|
(let ((a (+ 1 (expt 2 -64))) (b (expt 2 -65))) (+ a -1 b))
|
|
|
|
|
(let ((a (+ 1 (expt 2 -64))) (b (expt 2 -65))) (- a 1 (- b)))
|
2018-03-23 12:57:39 -07:00
|
|
|
|
(let ((a (expt 2 -1074)) (b 0.125)) (* a 8 b))
|
2008-11-30 05:57:33 +00:00
|
|
|
|
(let ((a 1.0)) (* a 0))
|
|
|
|
|
(let ((a 1.0)) (* a 2.0 0))
|
|
|
|
|
(let ((a 1.0)) (/ 0 a))
|
|
|
|
|
(let ((a 1.0)) (/ 3 a 2))
|
|
|
|
|
(let ((a most-positive-fixnum) (b 2.0)) (* a 2 b))
|
|
|
|
|
(let ((a 3) (b 2)) (/ a b 1.0))
|
2020-08-03 15:29:41 +02:00
|
|
|
|
(let ((a -0.0)) (+ a))
|
|
|
|
|
(let ((a -0.0)) (- a))
|
|
|
|
|
(let ((a -0.0)) (* a))
|
|
|
|
|
(let ((a -0.0)) (min a))
|
|
|
|
|
(let ((a -0.0)) (max a))
|
2008-11-30 05:57:33 +00:00
|
|
|
|
(/ 3 -1)
|
|
|
|
|
(+ 4 3 2 1)
|
|
|
|
|
(+ 4 3 2.0 1)
|
|
|
|
|
(- 4 3 2 1) ; not new, for reference
|
|
|
|
|
(- 4 3 2.0 1) ; not new, for reference
|
|
|
|
|
(* 4 3 2 1)
|
|
|
|
|
(* 4 3 2.0 1)
|
|
|
|
|
(/ 4 3 2 1)
|
|
|
|
|
(/ 4 3 2.0 1)
|
|
|
|
|
(let ((a 3) (b 2)) (+ a b 1))
|
|
|
|
|
(let ((a 3) (b 2)) (+ a b -1))
|
|
|
|
|
(let ((a 3) (b 2)) (- a b 1))
|
|
|
|
|
(let ((a 3) (b 2)) (- a b -1))
|
|
|
|
|
(let ((a 3) (b 2)) (+ a b a 1))
|
|
|
|
|
(let ((a 3) (b 2)) (+ a b a -1))
|
|
|
|
|
(let ((a 3) (b 2)) (- a b a 1))
|
|
|
|
|
(let ((a 3) (b 2)) (- a b a -1))
|
|
|
|
|
(let ((a 3) (b 2)) (* a b -1))
|
|
|
|
|
(let ((a 3) (b 2)) (* a -1))
|
|
|
|
|
(let ((a 3) (b 2)) (/ a b 1))
|
|
|
|
|
(let ((a 3) (b 2)) (/ (+ a b) 1))
|
|
|
|
|
|
|
|
|
|
;; coverage test
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 2 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 2 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 2.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 2.0 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 2.0 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 0 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 0 2.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 0.0 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 0.0 2.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ a 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ a 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 0 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 0.0 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ c 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ c 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 0 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 0.0 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ a b 0 c 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 0 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 0 a b))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 0 a b c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 1 2 3))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 3.0 2.0 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 3.0 2.0 1 4))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ a 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ a -1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 1 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ -1 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ c 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ c -1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 1 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ -1 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ a b 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ a b 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ a b -1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ a b 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ 1 a b c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ a b c 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ a b c 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (+ a b c -1))
|
|
|
|
|
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (-))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 2 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 2 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 2.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 2.0 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 2.0 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 0 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 0 2.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 0.0 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 0.0 2.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- a 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- a 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 0 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 0.0 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- c 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- c 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 0 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 0.0 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- a b 0 c 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 0 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 0 a b))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 0 a b c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 1 2 3))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 3.0 2.0 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 3.0 2.0 1 4))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- a 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- a -1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 1 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- -1 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- c 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- c -1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 1 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- -1 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- a b 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- a b 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- a b -1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- a b 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- 1 a b c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- a b c 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- a b c 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (- a b c -1))
|
|
|
|
|
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (*))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 2 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 2 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 2.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 2.0 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 2.0 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 0 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 0 2.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 0.0 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 0.0 2.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* a 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* a 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 0 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 0.0 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* c 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* c 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 0 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 0.0 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* a b 0 c 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 0 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 0 a b))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 0 a b c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 1 2 3))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 3.0 2.0 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 3.0 2.0 1 4))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* a 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* a -1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 1 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* -1 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* c 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* c -1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 1 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* -1 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* a b 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* a b 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* a b -1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* a b 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* 1 a b c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* a b c 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* a b c 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (* a b c -1))
|
|
|
|
|
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 2 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 2 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 2.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 2.0 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 2.0 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 0 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 0 2.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 0.0 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 0.0 2.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ a 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ a 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 0 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 0.0 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ c 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ c 0.0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 0 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 0.0 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ a b 0 c 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 0 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 0 a b))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 0 a b c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 1 2 3))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 3.0 2.0 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 3.0 2.0 1 4))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ a 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ a -1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 1 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ -1 a))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ c 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ c -1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 1 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ -1 c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ a b 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ a b 1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ a b -1))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ a b 2))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ 1 a b c))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ a b c 0))
|
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ a b c 1))
|
2017-02-15 21:03:05 +05:30
|
|
|
|
(let ((a 3) (b 2) (c 1.0)) (/ a b c -1))
|
2018-03-23 12:57:39 -07:00
|
|
|
|
|
|
|
|
|
(let ((a t)) (logand 0 a))
|
|
|
|
|
|
2017-02-15 21:03:05 +05:30
|
|
|
|
;; Test switch bytecode
|
2017-02-07 19:35:20 +05:30
|
|
|
|
(let ((a 3)) (cond ((eq a 1) 'one) ((eq a 2) 'two) ((eq a 3) 'three) (t t)))
|
|
|
|
|
(let ((a 'three)) (cond ((eq a 'one) 1) ((eq a 2) 'two) ((eq a 'three) 3)
|
|
|
|
|
(t t)))
|
|
|
|
|
(let ((a 2)) (cond ((eq a 'one) 1) ((eq a 1) 'one) ((eq a 2) 'two)
|
2017-02-13 13:18:54 +05:30
|
|
|
|
(t nil)))
|
|
|
|
|
(let ((a 2.0)) (cond ((eql a 2) 'incorrect) ((eql a 2.00) 'correct)))
|
|
|
|
|
(let ((a "foobar")) (cond ((equal "notfoobar" a) 'incorrect)
|
|
|
|
|
((equal 1 a) 'incorrect)
|
|
|
|
|
((equal a "foobar") 'correct)
|
2017-02-15 21:03:05 +05:30
|
|
|
|
(t 'incorrect)))
|
|
|
|
|
(let ((a "foobar") (l t)) (pcase a
|
|
|
|
|
("bar" 'incorrect)
|
|
|
|
|
("foobar" (while l
|
|
|
|
|
a (setq l nil))
|
|
|
|
|
'correct)))
|
|
|
|
|
(let ((a 'foobar) (l t)) (cl-case a
|
|
|
|
|
('foo 'incorrect)
|
|
|
|
|
('bar 'incorrect)
|
|
|
|
|
('foobar (while l
|
|
|
|
|
a (setq l nil))
|
|
|
|
|
'correct)))
|
|
|
|
|
(let ((a 'foobar) (l t)) (cond
|
|
|
|
|
((eq a 'bar) 'incorrect)
|
|
|
|
|
((eq a 'foo) 'incorrect)
|
|
|
|
|
((eq a 'bar) 'incorrect)
|
|
|
|
|
(t (while l
|
|
|
|
|
a (setq l nil))
|
|
|
|
|
'correct)))
|
|
|
|
|
(let ((a 'foobar) (l t)) (cond
|
|
|
|
|
((eq a 'bar) 'incorrect)
|
|
|
|
|
((eq a 'foo) 'incorrect)
|
|
|
|
|
((eq a 'foobar)
|
|
|
|
|
(while l
|
|
|
|
|
a (setq l nil))
|
|
|
|
|
'correct)
|
2017-04-22 21:51:43 +05:30
|
|
|
|
(t 'incorrect)))
|
|
|
|
|
(let ((a))
|
|
|
|
|
(cond ((eq a 'foo) 'incorrect)
|
|
|
|
|
(t)))
|
|
|
|
|
(let ((a))
|
|
|
|
|
(cond ((eq a 'foo) 'incorrect)
|
2018-06-16 07:44:58 -07:00
|
|
|
|
('correct)))
|
|
|
|
|
;; Bug#31734
|
|
|
|
|
(let ((variable 0))
|
|
|
|
|
(cond
|
|
|
|
|
((eq variable 'default)
|
|
|
|
|
(message "equal"))
|
|
|
|
|
(t
|
2019-05-17 11:25:06 +02:00
|
|
|
|
(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)
|
2019-05-22 12:36:03 +02:00
|
|
|
|
((equal x "c") 'incorrect)))
|
|
|
|
|
;; Multi-value clauses
|
|
|
|
|
(mapcar (lambda (x) (cond ((eq x 'a) 11)
|
|
|
|
|
((memq x '(b a c d)) 22)
|
|
|
|
|
((eq x 'c) 33)
|
|
|
|
|
((eq x 'e) 44)
|
|
|
|
|
((memq x '(d f g)) 55)
|
|
|
|
|
(t 99)))
|
|
|
|
|
'(a b c d e f g h))
|
|
|
|
|
(mapcar (lambda (x) (cond ((eql x 1) 11)
|
|
|
|
|
((memq x '(a b c)) 22)
|
|
|
|
|
((memql x '(2 1 4 1e-3)) 33)
|
|
|
|
|
((eq x 'd) 44)
|
|
|
|
|
((eql x #x10000000000000000))))
|
|
|
|
|
'(1 2 4 1e-3 a b c d 1.0 #x10000000000000000))
|
|
|
|
|
(mapcar (lambda (x) (cond ((eq x 'a) 11)
|
|
|
|
|
((memq x '(b d)) 22)
|
|
|
|
|
((equal x '(a . b)) 33)
|
|
|
|
|
((member x '(b c 1.5 2.5 "X" (d))) 44)
|
|
|
|
|
((eql x 3.14) 55)
|
|
|
|
|
((memql x '(9 0.5 1.5 q)) 66)
|
|
|
|
|
(t 99)))
|
|
|
|
|
'(a b c d (d) (a . b) "X" 0.5 1.5 3.14 9 9.0))
|
2019-06-07 17:04:10 +02:00
|
|
|
|
;; Multi-switch cond form
|
|
|
|
|
(mapcar (lambda (p) (let ((x (car p)) (y (cadr p)))
|
|
|
|
|
(cond ((consp x) 11)
|
|
|
|
|
((eq x 'a) 22)
|
|
|
|
|
((memql x '(b 7 a -3)) 33)
|
|
|
|
|
((equal y "a") 44)
|
|
|
|
|
((memq y '(c d e)) 55)
|
|
|
|
|
((booleanp x) 66)
|
|
|
|
|
((eq x 'q) 77)
|
|
|
|
|
((memq x '(r s)) 88)
|
|
|
|
|
((eq x 't) 99)
|
|
|
|
|
(t 999))))
|
|
|
|
|
'((a c) (b c) (7 c) (-3 c) (nil nil) (t c) (q c) (r c) (s c)
|
2020-02-21 12:16:20 +01:00
|
|
|
|
(t c) (x "a") (x "c") (x c) (x d) (x e)))
|
|
|
|
|
|
2021-04-07 13:11:43 +02:00
|
|
|
|
(mapcar (lambda (x) (ignore-errors (cond ((member '(a . b) x) 1)
|
|
|
|
|
((equal x '(c)) 2))))
|
2020-08-19 14:59:29 +02:00
|
|
|
|
'(((a . b)) a b (c) (d)))
|
2021-04-07 13:11:43 +02:00
|
|
|
|
(mapcar (lambda (x) (ignore-errors (cond ((memq '(a . b) x) 1)
|
|
|
|
|
((equal x '(c)) 2))))
|
2020-08-19 14:59:29 +02:00
|
|
|
|
'(((a . b)) a b (c) (d)))
|
2021-04-07 13:11:43 +02:00
|
|
|
|
(mapcar (lambda (x) (ignore-errors (cond ((member '(a b) x) 1)
|
|
|
|
|
((equal x '(c)) 2))))
|
2020-08-19 14:59:29 +02:00
|
|
|
|
'(((a b)) a b (c) (d)))
|
2021-04-07 13:11:43 +02:00
|
|
|
|
(mapcar (lambda (x) (ignore-errors (cond ((memq '(a b) x) 1)
|
|
|
|
|
((equal x '(c)) 2))))
|
2020-10-31 14:16:25 +01:00
|
|
|
|
'(((a b)) a b (c) (d)))
|
|
|
|
|
|
|
|
|
|
(assoc 'b '((a 1) (b 2) (c 3)))
|
|
|
|
|
(assoc "b" '(("a" 1) ("b" 2) ("c" 3)))
|
|
|
|
|
(let ((x '((a 1) (b 2) (c 3)))) (assoc 'c x))
|
Constprop of lexical variables
Lexical variables bound to a constant value (symbol, number or string)
are substituted at their point of use and the variable then eliminated
if possible. Example:
(let ((x (+ 2 3))) (f x)) => (f 5)
This reduces code size, eliminates stack operations, and enables
further optimisations. The implementation is conservative, and is
strongly curtailed by the presence of variable mutation, conditions
and loops.
* lisp/emacs-lisp/byte-opt.el
(byte-optimize-enable-variable-constprop)
(byte-optimize-warn-eliminated-variable): New constants.
(byte-optimize--lexvars, byte-optimize--vars-outside-condition)
(byte-optimize--vars-outside-loop, byte-optimize--dynamic-vars):
New dynamic variables.
(byte-optimize--substitutable-p, byte-optimize-let-form):
New functions.
(byte-optimize-form-code-walker): Adapt clauses for variable
constprop, and add clauses for 'setq' and 'defvar'.
* test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-test-var)
(bytecomp-test-get-var, bytecomp-test-identity)
(byte-opt-testsuite-arith-data): Add test cases.
2021-02-06 18:34:45 +01:00
|
|
|
|
(assoc 'a '((a 1) (b 2) (c 3)) (lambda (u v) (not (equal u v))))
|
|
|
|
|
|
|
|
|
|
;; Constprop test cases
|
|
|
|
|
(let ((a 'alpha) (b (concat "be" "ta")) (c nil) (d t) (e :gamma)
|
|
|
|
|
(f '(delta epsilon)))
|
|
|
|
|
(list a b c d e f))
|
|
|
|
|
|
|
|
|
|
(let ((x 1) (y (+ 3 4)))
|
|
|
|
|
(list
|
|
|
|
|
(let (q (y x) (z y))
|
|
|
|
|
(if q x (list x y z)))))
|
|
|
|
|
|
|
|
|
|
(let* ((x 3) (y (* x 2)) (x (1+ y)))
|
|
|
|
|
x)
|
|
|
|
|
|
|
|
|
|
(let ((x 1) (bytecomp-test-var 2) (y 3))
|
2021-04-07 13:11:43 +02:00
|
|
|
|
(list x bytecomp-test-var (bytecomp-test-get-var) y))
|
Constprop of lexical variables
Lexical variables bound to a constant value (symbol, number or string)
are substituted at their point of use and the variable then eliminated
if possible. Example:
(let ((x (+ 2 3))) (f x)) => (f 5)
This reduces code size, eliminates stack operations, and enables
further optimisations. The implementation is conservative, and is
strongly curtailed by the presence of variable mutation, conditions
and loops.
* lisp/emacs-lisp/byte-opt.el
(byte-optimize-enable-variable-constprop)
(byte-optimize-warn-eliminated-variable): New constants.
(byte-optimize--lexvars, byte-optimize--vars-outside-condition)
(byte-optimize--vars-outside-loop, byte-optimize--dynamic-vars):
New dynamic variables.
(byte-optimize--substitutable-p, byte-optimize-let-form):
New functions.
(byte-optimize-form-code-walker): Adapt clauses for variable
constprop, and add clauses for 'setq' and 'defvar'.
* test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-test-var)
(bytecomp-test-get-var, bytecomp-test-identity)
(byte-opt-testsuite-arith-data): Add test cases.
2021-02-06 18:34:45 +01:00
|
|
|
|
|
|
|
|
|
(progn
|
|
|
|
|
(defvar d)
|
|
|
|
|
(let ((x 'a) (y 'b)) (list x y)))
|
|
|
|
|
|
|
|
|
|
(let ((x 2))
|
|
|
|
|
(list x (setq x 13) (setq x (* x 2)) x))
|
|
|
|
|
|
|
|
|
|
(let ((x 'a) (y 'b))
|
|
|
|
|
(setq y x
|
|
|
|
|
x (cons 'c y)
|
|
|
|
|
y x)
|
|
|
|
|
(list x y))
|
|
|
|
|
|
|
|
|
|
(let ((x 3))
|
|
|
|
|
(let ((y x) z)
|
|
|
|
|
(setq x 5)
|
|
|
|
|
(setq y (+ y 8))
|
|
|
|
|
(setq z (if (bytecomp-test-identity t)
|
|
|
|
|
(progn
|
|
|
|
|
(setq x (+ x 1))
|
|
|
|
|
(list x y))
|
|
|
|
|
(setq x (+ x 2))
|
|
|
|
|
(list x y)))
|
|
|
|
|
(list x y z)))
|
|
|
|
|
|
|
|
|
|
(let ((i 1) (s 0) (x 13))
|
|
|
|
|
(while (< i 5)
|
|
|
|
|
(setq s (+ s i))
|
|
|
|
|
(setq i (1+ i)))
|
|
|
|
|
(list s x i))
|
|
|
|
|
|
|
|
|
|
(let ((x 2))
|
2021-04-09 18:42:12 +02:00
|
|
|
|
(list (or (bytecomp-test-identity 'a) (setq x 3)) x))
|
2021-04-09 18:59:09 +02:00
|
|
|
|
|
2021-08-05 11:50:25 +02:00
|
|
|
|
(mapcar (lambda (b)
|
|
|
|
|
(let ((a nil))
|
|
|
|
|
(+ 0
|
|
|
|
|
(progn
|
|
|
|
|
(setq a b)
|
|
|
|
|
(setq b 1)
|
|
|
|
|
a))))
|
|
|
|
|
'(10))
|
|
|
|
|
|
2021-04-09 18:59:09 +02:00
|
|
|
|
(let* ((x 1)
|
|
|
|
|
(y (condition-case x
|
|
|
|
|
(/ 1 0)
|
|
|
|
|
(arith-error x))))
|
|
|
|
|
(list x y))
|
2021-04-11 12:38:37 +02:00
|
|
|
|
|
|
|
|
|
(funcall
|
|
|
|
|
(condition-case x
|
|
|
|
|
(/ 1 0)
|
|
|
|
|
(arith-error (prog1 (lambda (y) (+ y x))
|
|
|
|
|
(setq x 10))))
|
|
|
|
|
4)
|
2021-04-07 11:31:07 +02:00
|
|
|
|
|
2021-09-22 11:03:30 +02:00
|
|
|
|
;; Loop constprop: set the inner and outer variables in the inner
|
|
|
|
|
;; and outer loops, all combinations.
|
|
|
|
|
(bytecomp-test-loop nil nil nil nil )
|
|
|
|
|
(bytecomp-test-loop nil nil nil (setq x 6))
|
|
|
|
|
(bytecomp-test-loop nil nil (setq x 5) nil )
|
|
|
|
|
(bytecomp-test-loop nil nil (setq x 5) (setq x 6))
|
|
|
|
|
(bytecomp-test-loop nil (setq x 4) nil nil )
|
|
|
|
|
(bytecomp-test-loop nil (setq x 4) nil (setq x 6))
|
|
|
|
|
(bytecomp-test-loop nil (setq x 4) (setq x 5) nil )
|
|
|
|
|
(bytecomp-test-loop nil (setq x 4) (setq x 5) (setq x 6))
|
|
|
|
|
(bytecomp-test-loop (setq x 3) nil nil nil )
|
|
|
|
|
(bytecomp-test-loop (setq x 3) nil nil (setq x 6))
|
|
|
|
|
(bytecomp-test-loop (setq x 3) nil (setq x 5) nil )
|
|
|
|
|
(bytecomp-test-loop (setq x 3) nil (setq x 5) (setq x 6))
|
|
|
|
|
(bytecomp-test-loop (setq x 3) (setq x 4) nil nil )
|
|
|
|
|
(bytecomp-test-loop (setq x 3) (setq x 4) nil (setq x 6))
|
|
|
|
|
(bytecomp-test-loop (setq x 3) (setq x 4) (setq x 5) nil )
|
|
|
|
|
(bytecomp-test-loop (setq x 3) (setq x 4) (setq x 5) (setq x 6))
|
|
|
|
|
|
2021-04-07 11:31:07 +02:00
|
|
|
|
;; No error, no success handler.
|
|
|
|
|
(condition-case x
|
|
|
|
|
(list 42)
|
|
|
|
|
(error (cons 'bad x)))
|
|
|
|
|
;; Error, no success handler.
|
|
|
|
|
(condition-case x
|
|
|
|
|
(/ 1 0)
|
|
|
|
|
(error (cons 'bad x)))
|
|
|
|
|
;; No error, success handler.
|
|
|
|
|
(condition-case x
|
|
|
|
|
(list 42)
|
|
|
|
|
(error (cons 'bad x))
|
|
|
|
|
(:success (cons 'good x)))
|
|
|
|
|
;; Error, success handler.
|
|
|
|
|
(condition-case x
|
|
|
|
|
(/ 1 0)
|
|
|
|
|
(error (cons 'bad x))
|
|
|
|
|
(:success (cons 'good x)))
|
|
|
|
|
;; Verify that the success code is not subject to the error handlers.
|
|
|
|
|
(condition-case x
|
|
|
|
|
(list 42)
|
|
|
|
|
(error (cons 'bad x))
|
|
|
|
|
(:success (/ (car x) 0)))
|
|
|
|
|
;; Check variable scoping on success.
|
|
|
|
|
(let ((x 2))
|
|
|
|
|
(condition-case x
|
|
|
|
|
(list x)
|
|
|
|
|
(error (list 'bad x))
|
|
|
|
|
(:success (list 'good x))))
|
|
|
|
|
;; Check variable scoping on failure.
|
|
|
|
|
(let ((x 2))
|
|
|
|
|
(condition-case x
|
|
|
|
|
(/ 1 0)
|
|
|
|
|
(error (list 'bad x))
|
|
|
|
|
(:success (list 'good x))))
|
|
|
|
|
;; Check capture of mutated result variable.
|
|
|
|
|
(funcall
|
|
|
|
|
(condition-case x
|
|
|
|
|
3
|
|
|
|
|
(:success (prog1 (lambda (y) (+ y x))
|
|
|
|
|
(setq x 10))))
|
|
|
|
|
4)
|
|
|
|
|
;; Check for-effect context, on error.
|
|
|
|
|
(let ((f (lambda (x)
|
|
|
|
|
(condition-case nil
|
|
|
|
|
(/ 1 0)
|
|
|
|
|
(error 'bad)
|
|
|
|
|
(:success 'good))
|
|
|
|
|
(1+ x))))
|
|
|
|
|
(funcall f 3))
|
|
|
|
|
;; Check for-effect context, on success.
|
|
|
|
|
(let ((f (lambda (x)
|
|
|
|
|
(condition-case nil
|
|
|
|
|
nil
|
|
|
|
|
(error 'bad)
|
|
|
|
|
(:success 'good))
|
|
|
|
|
(1+ x))))
|
|
|
|
|
(funcall f 3))
|
2021-07-27 17:26:26 +02:00
|
|
|
|
|
|
|
|
|
;; Check `not' in cond switch (bug#49746).
|
|
|
|
|
(mapcar (lambda (x) (cond ((equal x "a") 1)
|
|
|
|
|
((member x '("b" "c")) 2)
|
|
|
|
|
((not x) 3)))
|
|
|
|
|
'("a" "b" "c" "d" nil))
|
2021-07-29 15:35:55 +02:00
|
|
|
|
|
|
|
|
|
;; `let' and `let*' optimisations with body being constant or variable
|
|
|
|
|
(let* (a
|
|
|
|
|
(b (progn (setq a (cons 1 a)) 2))
|
|
|
|
|
(c (1+ b))
|
|
|
|
|
(d (list a c)))
|
|
|
|
|
d)
|
|
|
|
|
(let ((a nil))
|
|
|
|
|
(let ((b (progn (setq a (cons 1 a)) 2))
|
|
|
|
|
(c (progn (setq a (cons 3 a))))
|
|
|
|
|
(d (list a)))
|
|
|
|
|
d))
|
|
|
|
|
(let* ((_a 1)
|
|
|
|
|
(_b 2))
|
|
|
|
|
'z)
|
|
|
|
|
(let ((_a 1)
|
|
|
|
|
(_b 2))
|
|
|
|
|
'z)
|
2021-09-25 12:15:21 +02:00
|
|
|
|
(let (x y)
|
|
|
|
|
y)
|
|
|
|
|
(let* (x y)
|
|
|
|
|
y)
|
|
|
|
|
(let (x y)
|
|
|
|
|
'a)
|
|
|
|
|
(let* (x y)
|
|
|
|
|
'a)
|
2021-07-28 21:07:58 +02:00
|
|
|
|
|
|
|
|
|
;; Check empty-list optimisations.
|
|
|
|
|
(mapcar (lambda (x) (member x nil)) '("a" 2 nil))
|
|
|
|
|
(mapcar (lambda (x) (memql x nil)) '(a 2 nil))
|
|
|
|
|
(mapcar (lambda (x) (memq x nil)) '(a nil))
|
|
|
|
|
(let ((n 0))
|
|
|
|
|
(list (mapcar (lambda (x) (member (setq n (1+ n)) nil)) '(a "nil"))
|
|
|
|
|
n))
|
|
|
|
|
(mapcar (lambda (x) (assoc x nil)) '("a" nil))
|
|
|
|
|
(mapcar (lambda (x) (assq x nil)) '(a nil))
|
|
|
|
|
(mapcar (lambda (x) (rassoc x nil)) '("a" nil))
|
|
|
|
|
(mapcar (lambda (x) (rassq x nil)) '(a nil))
|
|
|
|
|
(let ((n 0))
|
|
|
|
|
(list (mapcar (lambda (x) (assoc (setq n (1+ n)) nil)) '(a "nil"))
|
|
|
|
|
n))
|
2021-07-30 13:44:07 +02:00
|
|
|
|
|
|
|
|
|
;; Exercise variable-aliasing optimisations.
|
|
|
|
|
(let ((a (list 1)))
|
|
|
|
|
(let ((b a))
|
|
|
|
|
(let ((a (list 2)))
|
|
|
|
|
(list a b))))
|
|
|
|
|
|
|
|
|
|
(let ((a (list 1)))
|
|
|
|
|
(let ((a (list 2))
|
|
|
|
|
(b a))
|
|
|
|
|
(list a b)))
|
|
|
|
|
|
|
|
|
|
(let* ((a (list 1))
|
|
|
|
|
(b a)
|
|
|
|
|
(a (list 2)))
|
|
|
|
|
(condition-case a
|
|
|
|
|
(list a b)
|
|
|
|
|
(error (list 'error a b))))
|
|
|
|
|
|
|
|
|
|
(let* ((a (list 1))
|
|
|
|
|
(b a)
|
|
|
|
|
(a (list 2)))
|
|
|
|
|
(condition-case a
|
|
|
|
|
(/ 0)
|
|
|
|
|
(error (list 'error a b))))
|
|
|
|
|
|
|
|
|
|
(let* ((a (list 1))
|
|
|
|
|
(b a)
|
|
|
|
|
(a (list 2))
|
|
|
|
|
(f (list (lambda (x) (list x a)))))
|
|
|
|
|
(funcall (car f) 3))
|
|
|
|
|
|
|
|
|
|
(let* ((a (list 1))
|
|
|
|
|
(b a)
|
|
|
|
|
(f (list (lambda (x) (setq a x)))))
|
|
|
|
|
(funcall (car f) 3)
|
|
|
|
|
(list a b))
|
|
|
|
|
|
|
|
|
|
(let* ((a (list 1))
|
|
|
|
|
(b a)
|
|
|
|
|
(a (list 2))
|
|
|
|
|
(f (list (lambda (x) (setq a x)))))
|
|
|
|
|
(funcall (car f) 3)
|
|
|
|
|
(list a b))
|
2021-11-02 14:48:55 +01:00
|
|
|
|
|
|
|
|
|
(cond)
|
|
|
|
|
(mapcar (lambda (x) (cond ((= x 0)))) '(0 1))
|
2021-11-22 16:56:38 +01:00
|
|
|
|
|
|
|
|
|
;; These expressions give different results in lexbind and dynbind modes,
|
|
|
|
|
;; but in each the compiler and interpreter should agree!
|
|
|
|
|
;; (They look much the same but come in pairs exercising both the
|
|
|
|
|
;; `let' and `let*' paths.)
|
|
|
|
|
(let ((f (lambda (x)
|
|
|
|
|
(lambda ()
|
|
|
|
|
(let ((g (lambda () x)))
|
|
|
|
|
(let ((x 'a))
|
|
|
|
|
(list x (funcall g))))))))
|
|
|
|
|
(funcall (funcall f 'b)))
|
|
|
|
|
(let ((f (lambda (x)
|
|
|
|
|
(lambda ()
|
|
|
|
|
(let ((g (lambda () x)))
|
|
|
|
|
(let* ((x 'a))
|
|
|
|
|
(list x (funcall g))))))))
|
|
|
|
|
(funcall (funcall f 'b)))
|
|
|
|
|
(let ((f (lambda (x)
|
|
|
|
|
(lambda ()
|
|
|
|
|
(let ((g (lambda () x)))
|
|
|
|
|
(setq x (list x x))
|
|
|
|
|
(let ((x 'a))
|
|
|
|
|
(list x (funcall g))))))))
|
|
|
|
|
(funcall (funcall f 'b)))
|
|
|
|
|
(let ((f (lambda (x)
|
|
|
|
|
(lambda ()
|
|
|
|
|
(let ((g (lambda () x)))
|
|
|
|
|
(setq x (list x x))
|
|
|
|
|
(let* ((x 'a))
|
|
|
|
|
(list x (funcall g))))))))
|
|
|
|
|
(funcall (funcall f 'b)))
|
|
|
|
|
(let ((f (lambda (x)
|
|
|
|
|
(let ((g (lambda () x))
|
|
|
|
|
(h (lambda () (setq x (list x x)))))
|
|
|
|
|
(let ((x 'a))
|
|
|
|
|
(list x (funcall g) (funcall h)))))))
|
|
|
|
|
(funcall (funcall f 'b)))
|
|
|
|
|
(let ((f (lambda (x)
|
|
|
|
|
(let ((g (lambda () x))
|
|
|
|
|
(h (lambda () (setq x (list x x)))))
|
|
|
|
|
(let* ((x 'a))
|
|
|
|
|
(list x (funcall g) (funcall h)))))))
|
|
|
|
|
(funcall (funcall f 'b)))
|
2021-12-11 22:11:08 +01:00
|
|
|
|
|
|
|
|
|
;; Test constant-propagation of access to captured variables.
|
|
|
|
|
(let* ((x 2)
|
|
|
|
|
(f (lambda ()
|
|
|
|
|
(let ((y x)) (list y 3 y)))))
|
|
|
|
|
(funcall f))
|
2021-04-09 18:42:12 +02:00
|
|
|
|
)
|
|
|
|
|
"List of expressions for cross-testing interpreted and compiled code.")
|
2017-02-07 19:35:20 +05:30
|
|
|
|
|
2021-04-09 18:42:12 +02:00
|
|
|
|
(defconst bytecomp-tests--test-cases-lexbind-only
|
|
|
|
|
`(
|
|
|
|
|
;; This would infloop (and exhaust stack) with dynamic binding.
|
|
|
|
|
(let ((f #'car))
|
|
|
|
|
(let ((f (lambda (x) (cons (funcall f x) (cdr x)))))
|
|
|
|
|
(funcall f '(1 . 2))))
|
|
|
|
|
)
|
|
|
|
|
"List of expressions for cross-testing interpreted and compiled code.
|
|
|
|
|
These are only tested with lexical binding.")
|
|
|
|
|
|
|
|
|
|
(defun bytecomp-tests--eval-interpreted (form)
|
|
|
|
|
"Evaluate FORM using the Lisp interpreter, returning errors as a
|
|
|
|
|
special value."
|
|
|
|
|
(condition-case err
|
|
|
|
|
(eval form lexical-binding)
|
|
|
|
|
(error (list 'bytecomp-check-error (car err)))))
|
|
|
|
|
|
|
|
|
|
(defun bytecomp-tests--eval-compiled (form)
|
|
|
|
|
"Evaluate FORM using the Lisp byte-code compiler, returning errors as a
|
|
|
|
|
special value."
|
2011-02-14 16:21:42 -05:00
|
|
|
|
(let ((warning-minimum-log-level :emergency)
|
2021-04-09 18:42:12 +02:00
|
|
|
|
(byte-compile-warnings nil))
|
|
|
|
|
(condition-case err
|
|
|
|
|
(funcall (byte-compile (list 'lambda nil form)))
|
|
|
|
|
(error (list 'bytecomp-check-error (car err))))))
|
|
|
|
|
|
|
|
|
|
(ert-deftest bytecomp-tests-lexbind ()
|
|
|
|
|
"Check that various expressions behave the same when interpreted and
|
|
|
|
|
byte-compiled. Run with lexical binding."
|
|
|
|
|
(let ((lexical-binding t))
|
|
|
|
|
(dolist (form (append bytecomp-tests--test-cases-lexbind-only
|
|
|
|
|
bytecomp-tests--test-cases))
|
|
|
|
|
(ert-info ((prin1-to-string form) :prefix "form: ")
|
|
|
|
|
(should (equal (bytecomp-tests--eval-interpreted form)
|
|
|
|
|
(bytecomp-tests--eval-compiled form)))))))
|
|
|
|
|
|
|
|
|
|
(ert-deftest bytecomp-tests-dynbind ()
|
|
|
|
|
"Check that various expressions behave the same when interpreted and
|
|
|
|
|
byte-compiled. Run with dynamic binding."
|
|
|
|
|
(let ((lexical-binding nil))
|
|
|
|
|
(dolist (form bytecomp-tests--test-cases)
|
|
|
|
|
(ert-info ((prin1-to-string form) :prefix "form: ")
|
|
|
|
|
(should (equal (bytecomp-tests--eval-interpreted form)
|
|
|
|
|
(bytecomp-tests--eval-compiled form)))))))
|
2011-02-14 16:21:42 -05:00
|
|
|
|
|
2014-04-22 00:04:34 -07:00
|
|
|
|
(defun test-byte-comp-compile-and-load (compile &rest forms)
|
Prefer `declare` over a `put` of `list-indent-function`.
While at it, I enabled lexical-binding in the affected files.
* lisp/cedet/semantic/sb.el: Enable lexical-binding.
(semantic-sb-with-tag-buffer): Use `declare`.
* lisp/cedet/semantic/bovine/el.el: Enable lexical-binding.
(semantic-elisp-setup-form-parser): Use `declare`.
* lisp/emacs-lisp/ert.el:
* lisp/emacs-lisp/ert-x.el: Remove redundant `put`.
* lisp/emulation/cua-rect.el: Enable lexical-binding.
(cua--rectangle-operation, cua--rectangle-aux-replace): Use `declare`.
* lisp/mh-e/mh-acros.el: Enable lexical-binding.
(mh-do-in-gnu-emacs, mh-do-in-xemacs, mh-funcall-if-exists, defun-mh)
(defmacro-mh, with-mh-folder-updating, mh-in-show-buffer)
(mh-do-at-event-location, mh-iterate-on-messages-in-region)
(mh-iterate-on-range): Use `declare`.
* lisp/mh-e/mh-compat.el: Enable lexical-binding.
(mh-flet): Use `declare`.
* lisp/mh-e/mh-e.el: Enable lexical-binding.
(defgroup-mh, defcustom-mh, defface-mh): Use `declare`.
* lisp/net/sieve.el: Enable lexical-binding. Remove redundant :group args.
(sieve-activate, sieve-remove, sieve-edit-script): Remove unused arg
from the interactive spec.
(sieve-deactivate-all): Remove unused var `name`.
(sieve-change-region): Use `declare`.
* lisp/obsolete/fast-lock.el: Enable lexical-binding.
Remove redundant :group args. Remove XEmacs compat code.
(save-buffer-state): Remove macro.
(fast-lock-add-properties): Use `with-silent-modifications` instead.
* lisp/obsolete/lazy-lock.el: Enable lexical-binding.
Remove redundant :group args.
(do-while): Use `declare`.
(save-buffer-state): Remove macro.
(lazy-lock-fontify-rest-after-change, lazy-lock-defer-line-after-change)
(lazy-lock-defer-rest-after-change, lazy-lock-after-fontify-buffer)
(lazy-lock-after-unfontify-buffer, lazy-lock-fontify-region):
Use `with-silent-modifications` instead.
* lisp/obsolete/pgg.el: Enable lexical-binding. Remove XEmacs compat code.
(pgg-save-coding-system, pgg-as-lbt, pgg-process-when-success):
Use `declare`.
(pgg-add-passphrase-to-cache): Remove unused var `new-timer`.
(pgg-decrypt-region): Remove unused var `buf`.
* lisp/org/org-agenda.el (org-let, org-let2): Move from org-macs and
use `declare`.
* lisp/org/org-macs.el (org-let, org-let2): Move these functions that
are inherently harmful to your karma to the only package that uses them.
(org-scroll): Use `pcase` to avoid `eval` and use more readable syntax
for those integers standing for events.
* lisp/progmodes/antlr-mode.el: Enable lexical-binding.
(save-buffer-state-x): Use `declare` and `with-silent-modifications`.
* lisp/international/mule-util.el (with-coding-priority):
* lisp/cedet/ede/proj-comp.el (proj-comp-insert-variable-once):
* lisp/org/org-element.el (org-element-map):
* test/lisp/emacs-lisp/bytecomp-tests.el (test-byte-comp-compile-and-load):
* test/lisp/emacs-lisp/generator-tests.el (cps-testcase): Use `declare`.
2021-02-22 11:54:17 -05:00
|
|
|
|
(declare (indent 1))
|
2021-11-08 01:21:06 +01:00
|
|
|
|
(ert-with-temp-file elfile
|
|
|
|
|
:suffix ".el"
|
|
|
|
|
(ert-with-temp-file elcfile
|
|
|
|
|
:suffix ".elc"
|
|
|
|
|
(with-temp-buffer
|
2022-06-06 10:47:42 +02:00
|
|
|
|
(insert ";;; -*- lexical-binding: t -*-\n")
|
2021-11-08 01:21:06 +01:00
|
|
|
|
(dolist (form forms)
|
|
|
|
|
(print form (current-buffer)))
|
|
|
|
|
(write-region (point-min) (point-max) elfile nil 'silent))
|
|
|
|
|
(if compile
|
|
|
|
|
(let ((byte-compile-dest-file-function
|
|
|
|
|
(lambda (e) elcfile)))
|
|
|
|
|
(byte-compile-file elfile)))
|
|
|
|
|
(load elfile nil 'nomessage))))
|
2014-04-21 02:34:21 -07:00
|
|
|
|
|
|
|
|
|
(ert-deftest test-byte-comp-macro-expansion ()
|
2014-04-22 00:04:34 -07:00
|
|
|
|
(test-byte-comp-compile-and-load t
|
2014-04-21 02:34:21 -07:00
|
|
|
|
'(progn (defmacro abc (arg) 1) (defun def () (abc 2))))
|
|
|
|
|
(should (equal (funcall 'def) 1)))
|
|
|
|
|
|
|
|
|
|
(ert-deftest test-byte-comp-macro-expansion-eval-and-compile ()
|
2014-04-22 00:04:34 -07:00
|
|
|
|
(test-byte-comp-compile-and-load t
|
2014-04-21 02:34:21 -07:00
|
|
|
|
'(eval-and-compile (defmacro abc (arg) -1) (defun def () (abc 2))))
|
|
|
|
|
(should (equal (funcall 'def) -1)))
|
|
|
|
|
|
|
|
|
|
(ert-deftest test-byte-comp-macro-expansion-eval-when-compile ()
|
|
|
|
|
;; Make sure we interpret eval-when-compile forms properly. CLISP
|
|
|
|
|
;; and SBCL interpreter eval-when-compile (well, the CL equivalent)
|
|
|
|
|
;; in the same way.
|
2014-04-22 00:04:34 -07:00
|
|
|
|
(test-byte-comp-compile-and-load t
|
2014-04-21 02:34:21 -07:00
|
|
|
|
'(eval-when-compile
|
|
|
|
|
(defmacro abc (arg) -10)
|
|
|
|
|
(defun abc-1 () (abc 2)))
|
|
|
|
|
'(defmacro abc-2 () (abc-1))
|
|
|
|
|
'(defun def () (abc-2)))
|
|
|
|
|
(should (equal (funcall 'def) -10)))
|
|
|
|
|
|
|
|
|
|
(ert-deftest test-byte-comp-macro-expand-lexical-override ()
|
|
|
|
|
;; Intuitively, one might expect the defmacro to override the
|
|
|
|
|
;; macrolet since macrolet's is explicitly called out as being
|
|
|
|
|
;; equivalent to toplevel, but CLISP and SBCL both evaluate the form
|
|
|
|
|
;; this way, so we should too.
|
2014-04-22 00:04:34 -07:00
|
|
|
|
(test-byte-comp-compile-and-load t
|
2014-04-21 02:34:21 -07:00
|
|
|
|
'(require 'cl-lib)
|
|
|
|
|
'(cl-macrolet ((m () 4))
|
|
|
|
|
(defmacro m () 5)
|
|
|
|
|
(defun def () (m))))
|
|
|
|
|
(should (equal (funcall 'def) 4)))
|
2011-02-14 16:21:42 -05:00
|
|
|
|
|
2020-12-02 11:29:26 +01:00
|
|
|
|
|
|
|
|
|
;;;; Warnings.
|
|
|
|
|
|
2014-11-08 12:46:21 -05:00
|
|
|
|
(ert-deftest bytecomp-tests--warnings ()
|
|
|
|
|
(with-current-buffer (get-buffer-create "*Compile-Log*")
|
|
|
|
|
(let ((inhibit-read-only t)) (erase-buffer)))
|
2020-08-19 14:43:11 +01:00
|
|
|
|
(mapc #'fmakunbound '(my-test0 my--test11 my--test12 my--test2))
|
2014-11-08 12:46:21 -05:00
|
|
|
|
(test-byte-comp-compile-and-load t
|
|
|
|
|
'(progn
|
|
|
|
|
(defun my-test0 ()
|
|
|
|
|
(my--test11 3)
|
|
|
|
|
(my--test12 3)
|
|
|
|
|
(my--test2 5))
|
|
|
|
|
(defmacro my--test11 (arg) (+ arg 1))
|
|
|
|
|
(eval-and-compile
|
|
|
|
|
(defmacro my--test12 (arg) (+ arg 1))
|
|
|
|
|
(defun my--test2 (arg) (+ arg 1)))))
|
|
|
|
|
(with-current-buffer (get-buffer-create "*Compile-Log*")
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
;; Should warn that mt--test1[12] are first used as functions.
|
2015-06-21 20:27:48 +03:00
|
|
|
|
;; The second alternative is for when the file name is so long
|
|
|
|
|
;; that pretty-printing starts the message on the next line.
|
|
|
|
|
(should (or (re-search-forward "my--test11:\n.*macro" nil t)
|
|
|
|
|
(re-search-forward "my--test11:\n.*:\n.*macro" nil t)))
|
|
|
|
|
(should (or (re-search-forward "my--test12:\n.*macro" nil t)
|
|
|
|
|
(re-search-forward "my--test12:\n.*:\n.*macro" nil t)))
|
2014-11-08 12:46:21 -05:00
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
;; Should not warn that mt--test2 is not known to be defined.
|
|
|
|
|
(should-not (re-search-forward "my--test2" nil t))))
|
|
|
|
|
|
2020-11-22 07:19:11 +01:00
|
|
|
|
(defmacro bytecomp--with-warning-test (re-warning &rest form)
|
|
|
|
|
(declare (indent 1))
|
|
|
|
|
`(with-current-buffer (get-buffer-create "*Compile-Log*")
|
|
|
|
|
(let ((inhibit-read-only t)) (erase-buffer))
|
|
|
|
|
(byte-compile ,@form)
|
2021-04-09 18:49:16 +02:00
|
|
|
|
(ert-info ((prin1-to-string (buffer-string)) :prefix "buffer: ")
|
|
|
|
|
(should (re-search-forward ,(string-replace " " "[ \n]+" re-warning))))))
|
2020-11-22 07:19:11 +01:00
|
|
|
|
|
2019-05-27 20:36:41 -04:00
|
|
|
|
(ert-deftest bytecomp-warn-wrong-args ()
|
2020-11-22 07:19:11 +01:00
|
|
|
|
(bytecomp--with-warning-test "remq.*3.*2"
|
|
|
|
|
'(remq 1 2 3)))
|
2019-05-27 20:36:41 -04:00
|
|
|
|
|
|
|
|
|
(ert-deftest bytecomp-warn-wrong-args-subr ()
|
2020-11-22 07:19:11 +01:00
|
|
|
|
(bytecomp--with-warning-test "safe-length.*3.*1"
|
|
|
|
|
'(safe-length 1 2 3)))
|
|
|
|
|
|
|
|
|
|
(ert-deftest bytecomp-warn-variable-lacks-prefix ()
|
|
|
|
|
(bytecomp--with-warning-test "foo.*lacks a prefix"
|
|
|
|
|
'(defvar foo nil)))
|
2019-05-27 20:36:41 -04:00
|
|
|
|
|
2020-12-06 12:44:19 +01:00
|
|
|
|
(defvar bytecomp-tests--docstring (make-string 100 ?x))
|
|
|
|
|
|
|
|
|
|
(ert-deftest bytecomp-warn-wide-docstring/defconst ()
|
|
|
|
|
(bytecomp--with-warning-test "defconst.*foo.*wider than.*characters"
|
|
|
|
|
`(defconst foo t ,bytecomp-tests--docstring)))
|
|
|
|
|
|
|
|
|
|
(ert-deftest bytecomp-warn-wide-docstring/defvar ()
|
|
|
|
|
(bytecomp--with-warning-test "defvar.*foo.*wider than.*characters"
|
|
|
|
|
`(defvar foo t ,bytecomp-tests--docstring)))
|
|
|
|
|
|
2020-11-30 22:42:08 +01:00
|
|
|
|
(defmacro bytecomp--define-warning-file-test (file re-warning &optional reverse)
|
2020-12-01 13:34:17 +01:00
|
|
|
|
`(ert-deftest ,(intern (format "bytecomp/%s" file)) ()
|
2020-11-30 22:42:08 +01:00
|
|
|
|
(with-current-buffer (get-buffer-create "*Compile-Log*")
|
|
|
|
|
(let ((inhibit-read-only t)) (erase-buffer))
|
|
|
|
|
(byte-compile-file ,(ert-resource-file file))
|
|
|
|
|
(ert-info ((buffer-string) :prefix "buffer: ")
|
2021-04-09 18:49:16 +02:00
|
|
|
|
(,(if reverse 'should-not 'should)
|
2021-12-06 21:48:40 +01:00
|
|
|
|
(re-search-forward ,re-warning nil t))))))
|
2020-11-30 22:42:08 +01:00
|
|
|
|
|
2020-12-01 13:34:17 +01:00
|
|
|
|
(bytecomp--define-warning-file-test "error-lexical-var-with-add-hook.el"
|
|
|
|
|
"add-hook.*lexical var")
|
2020-11-30 22:42:08 +01:00
|
|
|
|
|
2020-12-01 13:34:17 +01:00
|
|
|
|
(bytecomp--define-warning-file-test "error-lexical-var-with-remove-hook.el"
|
|
|
|
|
"remove-hook.*lexical var")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "error-lexical-var-with-run-hook-with-args-until-failure.el"
|
|
|
|
|
"args-until-failure.*lexical var")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "error-lexical-var-with-run-hook-with-args-until-success.el"
|
|
|
|
|
"args-until-success.*lexical var")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "error-lexical-var-with-run-hook-with-args.el"
|
|
|
|
|
"args.*lexical var")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "error-lexical-var-with-symbol-value.el"
|
|
|
|
|
"symbol-value.*lexical var")
|
|
|
|
|
|
2020-12-03 17:08:28 +01:00
|
|
|
|
(bytecomp--define-warning-file-test "warn-autoload-not-on-top-level.el"
|
|
|
|
|
"compiler ignores.*autoload.*")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-callargs.el"
|
|
|
|
|
"with 2 arguments, but accepts only 1")
|
|
|
|
|
|
2021-07-22 15:00:17 +02:00
|
|
|
|
(bytecomp--define-warning-file-test "warn-callargs-defsubst.el"
|
|
|
|
|
"with 2 arguments, but accepts only 1")
|
|
|
|
|
|
2020-12-03 17:08:28 +01:00
|
|
|
|
(bytecomp--define-warning-file-test "warn-defcustom-nogroup.el"
|
|
|
|
|
"fails to specify containing group")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-defcustom-notype.el"
|
|
|
|
|
"fails to specify type")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-defvar-lacks-prefix.el"
|
|
|
|
|
"var.*foo.*lacks a prefix")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-format.el"
|
|
|
|
|
"called with 2 args to fill 1 format field")
|
|
|
|
|
|
2020-12-01 13:34:17 +01:00
|
|
|
|
(bytecomp--define-warning-file-test "warn-free-setq.el"
|
|
|
|
|
"free.*foo")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-free-variable-reference.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"free variable .bar")
|
2020-11-30 22:42:08 +01:00
|
|
|
|
|
2020-12-03 17:08:28 +01:00
|
|
|
|
(bytecomp--define-warning-file-test "warn-make-variable-buffer-local.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"make-variable-buffer-local. not called at toplevel")
|
2020-12-03 17:08:28 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-interactive-only.el"
|
|
|
|
|
"next-line.*interactive use only.*forward-line")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-lambda-malformed-interactive-spec.el"
|
|
|
|
|
"malformed interactive spec")
|
|
|
|
|
|
2020-12-01 04:46:33 +01:00
|
|
|
|
(bytecomp--define-warning-file-test "warn-obsolete-defun.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"foo-obsolete. is an obsolete function (as of 99.99)")
|
2020-12-01 04:46:33 +01:00
|
|
|
|
|
|
|
|
|
(defvar bytecomp--tests-obsolete-var nil)
|
|
|
|
|
(make-obsolete-variable 'bytecomp--tests-obsolete-var nil "99.99")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-obsolete-hook.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"bytecomp--tests-obsolete-var. is an obsolete variable (as of 99.99)")
|
2020-12-01 04:46:33 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-obsolete-variable-same-file.el"
|
|
|
|
|
"foo-obs.*obsolete.*99.99" t)
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-obsolete-variable.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"bytecomp--tests-obsolete-var. is an obsolete variable (as of 99.99)")
|
2020-12-01 04:46:33 +01:00
|
|
|
|
|
2020-12-22 05:44:47 +01:00
|
|
|
|
(bytecomp--define-warning-file-test "warn-obsolete-variable-bound.el"
|
|
|
|
|
"bytecomp--tests-obs.*obsolete.*99.99" t)
|
|
|
|
|
|
2020-12-03 17:08:28 +01:00
|
|
|
|
(bytecomp--define-warning-file-test "warn-redefine-defun-as-macro.el"
|
|
|
|
|
"as both function and macro")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-redefine-macro-as-defun.el"
|
|
|
|
|
"as both function and macro")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-redefine-defun.el"
|
|
|
|
|
"defined multiple")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-save-excursion.el"
|
|
|
|
|
"with-current.*rather than save-excursion")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-variable-let-bind-constant.el"
|
|
|
|
|
"let-bind constant")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-variable-let-bind-nonvariable.el"
|
|
|
|
|
"let-bind nonvariable")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-variable-set-constant.el"
|
2022-06-03 20:31:10 +02:00
|
|
|
|
"attempt to set constant")
|
2020-12-03 17:08:28 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-variable-set-nonvariable.el"
|
|
|
|
|
"variable reference to nonvariable")
|
2020-12-01 04:46:33 +01:00
|
|
|
|
|
2022-06-03 20:31:10 +02:00
|
|
|
|
(bytecomp--define-warning-file-test "warn-variable-setq-nonvariable.el"
|
|
|
|
|
"attempt to set non-variable")
|
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test "warn-variable-setq-odd.el"
|
|
|
|
|
"odd number of arguments")
|
|
|
|
|
|
2020-12-06 12:44:19 +01:00
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-autoload.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"autoload .foox. docstring wider than .* characters")
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-custom-declare-variable.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"custom-declare-variable .foo. docstring wider than .* characters")
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-defalias.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"defalias .foo. docstring wider than .* characters")
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-defconst.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"defconst .foo-bar. docstring wider than .* characters")
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-define-abbrev-table.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"define-abbrev-table .foo. docstring wider than .* characters")
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-define-obsolete-function-alias.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"defalias .foo. docstring wider than .* characters")
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-define-obsolete-variable-alias.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"defvaralias .foo. docstring wider than .* characters")
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-defun.el"
|
2021-12-06 21:51:37 +01:00
|
|
|
|
"Warning: docstring wider than .* characters")
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-defvar.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"defvar .foo-bar. docstring wider than .* characters")
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-defvaralias.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"defvaralias .foo-bar. docstring wider than .* characters")
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-ignore-fill-column.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"defvar .foo-bar. docstring wider than .* characters" 'reverse)
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-ignore-override.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"defvar .foo-bar. docstring wider than .* characters" 'reverse)
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
2021-11-22 08:08:11 +01:00
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-ignore-substitutions.el"
|
|
|
|
|
"defvar .foo-bar. docstring wider than .* characters" 'reverse)
|
|
|
|
|
|
2020-12-06 12:44:19 +01:00
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-ignore.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"defvar .foo-bar. docstring wider than .* characters" 'reverse)
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-multiline-first.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"defvar .foo-bar. docstring wider than .* characters")
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"warn-wide-docstring-multiline.el"
|
2021-04-09 18:49:16 +02:00
|
|
|
|
"defvar .foo-bar. docstring wider than .* characters")
|
2020-12-06 12:44:19 +01:00
|
|
|
|
|
2021-01-21 13:15:05 -05:00
|
|
|
|
(bytecomp--define-warning-file-test
|
|
|
|
|
"nowarn-inline-after-defvar.el"
|
|
|
|
|
"Lexical argument shadows" 'reverse)
|
|
|
|
|
|
2020-12-02 11:29:26 +01:00
|
|
|
|
|
|
|
|
|
;;;; Macro expansion.
|
|
|
|
|
|
|
|
|
|
(ert-deftest test-eager-load-macro-expansion ()
|
|
|
|
|
(test-byte-comp-compile-and-load nil
|
|
|
|
|
'(progn (defmacro abc (arg) 1) (defun def () (abc 2))))
|
|
|
|
|
(should (equal (funcall 'def) 1)))
|
|
|
|
|
|
|
|
|
|
(ert-deftest test-eager-load-macro-expansion-eval-and-compile ()
|
|
|
|
|
(test-byte-comp-compile-and-load nil
|
|
|
|
|
'(eval-and-compile (defmacro abc (arg) -1) (defun def () (abc 2))))
|
|
|
|
|
(should (equal (funcall 'def) -1)))
|
|
|
|
|
|
2014-04-22 00:04:34 -07:00
|
|
|
|
(ert-deftest test-eager-load-macro-expansion-eval-when-compile ()
|
|
|
|
|
;; Make sure we interpret eval-when-compile forms properly. CLISP
|
|
|
|
|
;; and SBCL interpreter eval-when-compile (well, the CL equivalent)
|
|
|
|
|
;; in the same way.
|
|
|
|
|
(test-byte-comp-compile-and-load nil
|
|
|
|
|
'(eval-when-compile
|
|
|
|
|
(defmacro abc (arg) -10)
|
|
|
|
|
(defun abc-1 () (abc 2)))
|
|
|
|
|
'(defmacro abc-2 () (abc-1))
|
|
|
|
|
'(defun def () (abc-2)))
|
|
|
|
|
(should (equal (funcall 'def) -10)))
|
|
|
|
|
|
|
|
|
|
(ert-deftest test-eager-load-macro-expand-lexical-override ()
|
|
|
|
|
;; Intuitively, one might expect the defmacro to override the
|
|
|
|
|
;; macrolet since macrolet's is explicitly called out as being
|
|
|
|
|
;; equivalent to toplevel, but CLISP and SBCL both evaluate the form
|
|
|
|
|
;; this way, so we should too.
|
|
|
|
|
(test-byte-comp-compile-and-load nil
|
|
|
|
|
'(require 'cl-lib)
|
|
|
|
|
'(cl-macrolet ((m () 4))
|
|
|
|
|
(defmacro m () 5)
|
|
|
|
|
(defun def () (m))))
|
|
|
|
|
(should (equal (funcall 'def) 4)))
|
|
|
|
|
|
2015-06-30 22:38:35 +02:00
|
|
|
|
(defmacro bytecomp-tests--with-temp-file (file-name-var &rest body)
|
|
|
|
|
(declare (indent 1))
|
|
|
|
|
(cl-check-type file-name-var symbol)
|
Prefer ert-with-temp-(directory|file)
* test/lisp/abbrev-tests.el (read-write-abbrev-file-test)
(read-write-abbrev-file-test-with-props)
(abbrev-edit-save-to-file-test):
* test/lisp/auth-source-tests.el (auth-source-test-netrc-create-secret)
(auth-source-delete):
* test/lisp/autoinsert-tests.el (autoinsert-tests-auto-insert-file):
* test/lisp/bookmark-tests.el (with-bookmark-test-save-load):
* test/lisp/buff-menu-tests.el (buff-menu-24962):
* test/lisp/calendar/icalendar-tests.el (icalendar-tests--do-test-export):
* test/lisp/calendar/todo-mode-tests.el (with-todo-test):
* test/lisp/dired-tests.el
(dired-test-bug27243-01, dired-test-bug27243-02)
(dired-test-bug27243-03, dired-test-bug27631)
(dired-test-bug27968, dired-test-with-temp-dirs):
* test/lisp/dired-x-tests.el (dired-test-bug25942):
* test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-tests--with-temp-file):
* test/lisp/emacs-lisp/check-declare-tests.el (check-declare-tests-scan)
(check-declare-tests-verify-mismatch):
* test/lisp/emacs-lisp/edebug-tests.el (edebug-tests-with-normal-env):
* test/lisp/emacs-lisp/package-tests.el (with-package-test)
(package-test-signed):
* test/lisp/emacs-lisp/testcover-tests.el (testcover-tests-markup-region)
(testcover-tests-run-test-case):
* test/lisp/emulation/viper-tests.el (viper-test-undo-kmacro):
* test/lisp/epg-tests.el (with-epg-tests):
* test/lisp/eshell/em-hist-tests.el (eshell-write-readonly-history):
* test/lisp/eshell/em-ls-tests.el (em-ls-test-bug27631):
* test/lisp/ffap-tests.el (ffap-tests-25243):
* test/lisp/files-tests.el (files-tests-bug-18141)
(files-tests-read-file-in-~, files-tests-make-directory)
(files-tests-copy-directory, files-tests-executable-find)
(files-tests-dont-rewrite-precious-files)
(files-tests--save-some-buffers):
* test/lisp/ls-lisp-tests.el (ls-lisp-test-bug27631):
* test/lisp/mail/uudecode-tests.el (uudecode-tests-decode-region-internal)
(uudecode-tests-decode-region-external):
* test/lisp/net/browse-url-tests.el (browse-url-tests-delete-temp-file):
* test/lisp/progmodes/elisp-mode-tests.el (xref--case-insensitive):
* test/lisp/progmodes/etags-tests.el (etags-buffer-local-tags-table-list):
* test/lisp/progmodes/flymake-tests.el (ruby-backend):
* test/lisp/progmodes/python-tests.el (python-tests-with-temp-file):
* test/lisp/progmodes/sql-tests.el (with-sql-test-connect-harness):
* test/lisp/saveplace-tests.el (saveplace-test-save-place-to-alist/file)
(saveplace-test-forget-unreadable-files)
(saveplace-test-place-alist-to-file):
* test/lisp/so-long-tests/spelling-tests.el:
* test/lisp/textmodes/reftex-tests.el (reftex-locate-bibliography-files)
(reftex-parse-from-file-test):
* test/lisp/thumbs-tests.el (thumbs-tests-thumbsdir/create-if-missing):
* test/lisp/vc/vc-bzr-tests.el (vc-bzr-test-bug9726)
(vc-bzr-test-bug9781, vc-bzr-test-faulty-bzr-autoloads):
* test/lisp/vc/diff-mode-tests.el (diff-mode-test-ignore-trailing-dashes):
* test/lisp/vc/ediff-ptch-tests.el (ediff-ptch-test-bug26084):
* test/lisp/wdired-tests.el (wdired-test-bug32173-01)
(wdired-test-bug32173-02, wdired-test-symlink-name)
(wdired-test-unfinished-edit-01, wdired-test-bug34915)
(wdired-test-bug39280):
* test/src/buffer-tests.el (test-kill-buffer-auto-save-default):
* test/src/filelock-tests.el (filelock-tests--fixture):
* test/src/inotify-tests.el (inotify-file-watch-simple):
* test/src/undo-tests.el (undo-test-file-modified): Prefer
'ert-with-temp-(directory|file)' to using 'make-temp-file' directly.
In some cases, this is just cleanup, but in several cases this fixes
bugs where an error would have lead to us not cleaning up.
2021-11-06 23:20:59 +01:00
|
|
|
|
`(ert-with-temp-file ,file-name-var
|
2015-06-30 22:38:35 +02:00
|
|
|
|
(unwind-protect
|
|
|
|
|
(progn ,@body)
|
2017-08-14 17:23:18 -04:00
|
|
|
|
(let ((elc (concat ,file-name-var ".elc")))
|
|
|
|
|
(if (file-exists-p elc) (delete-file elc))))))
|
2015-06-30 22:38:35 +02:00
|
|
|
|
|
|
|
|
|
(ert-deftest bytecomp-tests--unescaped-char-literals ()
|
|
|
|
|
"Check that byte compiling warns about unescaped character
|
|
|
|
|
literals (Bug#20852)."
|
|
|
|
|
(should (boundp 'lread--unescaped-character-literals))
|
2019-06-04 21:26:06 -04:00
|
|
|
|
(let ((byte-compile-error-on-warn t)
|
|
|
|
|
(byte-compile-debug t))
|
|
|
|
|
(bytecomp-tests--with-temp-file source
|
|
|
|
|
(write-region "(list ?) ?( ?; ?\" ?[ ?])" nil source)
|
|
|
|
|
(bytecomp-tests--with-temp-file destination
|
|
|
|
|
(let* ((byte-compile-dest-file-function (lambda (_) destination))
|
|
|
|
|
(err (should-error (byte-compile-file source))))
|
|
|
|
|
(should (equal (cdr err)
|
|
|
|
|
`(,(concat "unescaped character literals "
|
|
|
|
|
"`?\"', `?(', `?)', `?;', `?[', `?]' "
|
|
|
|
|
"detected, "
|
|
|
|
|
"`?\\\"', `?\\(', `?\\)', `?\\;', `?\\[', "
|
|
|
|
|
"`?\\]' expected!")))))))
|
|
|
|
|
;; But don't warn in subsequent compilations (Bug#36068).
|
|
|
|
|
(bytecomp-tests--with-temp-file source
|
|
|
|
|
(write-region "(list 1 2 3)" nil source)
|
|
|
|
|
(bytecomp-tests--with-temp-file destination
|
|
|
|
|
(let ((byte-compile-dest-file-function (lambda (_) destination)))
|
|
|
|
|
(should (byte-compile-file source)))))))
|
2015-06-30 22:38:35 +02:00
|
|
|
|
|
2017-07-14 00:32:34 -04:00
|
|
|
|
(ert-deftest bytecomp-tests-function-put ()
|
|
|
|
|
"Check `function-put' operates during compilation."
|
|
|
|
|
(bytecomp-tests--with-temp-file source
|
|
|
|
|
(dolist (form '((function-put 'bytecomp-tests--foo 'foo 1)
|
|
|
|
|
(function-put 'bytecomp-tests--foo 'bar 2)
|
|
|
|
|
(defmacro bytecomp-tests--foobar ()
|
|
|
|
|
`(cons ,(function-get 'bytecomp-tests--foo 'foo)
|
|
|
|
|
,(function-get 'bytecomp-tests--foo 'bar)))
|
|
|
|
|
(defvar bytecomp-tests--foobar 1)
|
|
|
|
|
(setq bytecomp-tests--foobar (bytecomp-tests--foobar))))
|
|
|
|
|
(print form (current-buffer)))
|
|
|
|
|
(write-region (point-min) (point-max) source nil 'silent)
|
2020-09-22 00:16:22 +02:00
|
|
|
|
(byte-compile-file source)
|
|
|
|
|
(load source)
|
2017-07-14 00:32:34 -04:00
|
|
|
|
(should (equal bytecomp-tests--foobar (cons 1 2)))))
|
|
|
|
|
|
2017-10-12 16:02:39 -07:00
|
|
|
|
(ert-deftest bytecomp-tests--test-no-warnings-with-advice ()
|
|
|
|
|
(defun f ())
|
|
|
|
|
(define-advice f (:around (oldfun &rest args) test)
|
|
|
|
|
(apply oldfun args))
|
|
|
|
|
(with-current-buffer (get-buffer-create "*Compile-Log*")
|
|
|
|
|
(let ((inhibit-read-only t)) (erase-buffer)))
|
|
|
|
|
(test-byte-comp-compile-and-load t '(defun f ()))
|
|
|
|
|
(with-current-buffer (get-buffer-create "*Compile-Log*")
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(should-not (search-forward "Warning" nil t))))
|
|
|
|
|
|
2018-03-26 21:56:33 -04:00
|
|
|
|
(ert-deftest bytecomp-test-featurep-warnings ()
|
|
|
|
|
(let ((byte-compile-log-buffer (generate-new-buffer " *Compile-Log*")))
|
|
|
|
|
(unwind-protect
|
|
|
|
|
(progn
|
|
|
|
|
(with-temp-buffer
|
|
|
|
|
(insert "\
|
|
|
|
|
\(defun foo ()
|
|
|
|
|
(an-undefined-function))
|
|
|
|
|
|
|
|
|
|
\(defun foo1 ()
|
|
|
|
|
(if (featurep 'xemacs)
|
|
|
|
|
(some-undefined-function-if)))
|
|
|
|
|
|
|
|
|
|
\(defun foo2 ()
|
|
|
|
|
(and (featurep 'xemacs)
|
|
|
|
|
(some-undefined-function-and)))
|
|
|
|
|
|
|
|
|
|
\(defun foo3 ()
|
|
|
|
|
(if (not (featurep 'emacs))
|
|
|
|
|
(some-undefined-function-not)))
|
|
|
|
|
|
|
|
|
|
\(defun foo4 ()
|
|
|
|
|
(or (featurep 'emacs)
|
|
|
|
|
(some-undefined-function-or)))
|
|
|
|
|
")
|
|
|
|
|
(byte-compile-from-buffer (current-buffer)))
|
|
|
|
|
(with-current-buffer byte-compile-log-buffer
|
|
|
|
|
(should (search-forward "an-undefined-function" nil t))
|
|
|
|
|
(should-not (search-forward "some-undefined-function" nil t))))
|
|
|
|
|
(if (buffer-live-p byte-compile-log-buffer)
|
|
|
|
|
(kill-buffer byte-compile-log-buffer)))))
|
|
|
|
|
|
2019-05-17 11:25:06 +02:00
|
|
|
|
(ert-deftest bytecomp-test--switch-duplicates ()
|
|
|
|
|
"Check that duplicates in switches are eliminated correctly (bug#35770)."
|
2019-07-09 03:25:13 -07:00
|
|
|
|
:expected-result (if byte-compile-cond-use-jump-table :passed :failed)
|
2019-05-17 11:25:06 +02:00
|
|
|
|
(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)))))
|
|
|
|
|
|
2019-06-12 15:59:19 +02:00
|
|
|
|
(defun test-suppression (form suppress match)
|
|
|
|
|
(let ((lexical-binding t)
|
|
|
|
|
(byte-compile-log-buffer (generate-new-buffer " *Compile-Log*")))
|
|
|
|
|
;; Check that we get a warning without suppression.
|
|
|
|
|
(with-current-buffer byte-compile-log-buffer
|
2019-06-16 17:35:36 -07:00
|
|
|
|
(setq-local fill-column 9999)
|
|
|
|
|
(setq-local warning-fill-column fill-column)
|
2019-06-12 15:59:19 +02:00
|
|
|
|
(let ((inhibit-read-only t))
|
|
|
|
|
(erase-buffer)))
|
|
|
|
|
(test-byte-comp-compile-and-load t form)
|
|
|
|
|
(with-current-buffer byte-compile-log-buffer
|
|
|
|
|
(unless match
|
|
|
|
|
(error "%s" (buffer-string)))
|
|
|
|
|
(goto-char (point-min))
|
2019-06-12 16:48:33 -07:00
|
|
|
|
(should (string-match match (buffer-string))))
|
2019-06-12 15:59:19 +02:00
|
|
|
|
;; And that it's gone now.
|
|
|
|
|
(with-current-buffer byte-compile-log-buffer
|
|
|
|
|
(let ((inhibit-read-only t))
|
|
|
|
|
(erase-buffer)))
|
|
|
|
|
(test-byte-comp-compile-and-load t
|
|
|
|
|
`(with-suppressed-warnings ,suppress
|
|
|
|
|
,form))
|
|
|
|
|
(with-current-buffer byte-compile-log-buffer
|
|
|
|
|
(goto-char (point-min))
|
2019-06-12 16:48:33 -07:00
|
|
|
|
(should-not (string-match match (buffer-string))))
|
2019-06-12 15:59:19 +02:00
|
|
|
|
;; Also check that byte compiled forms are identical.
|
|
|
|
|
(should (equal (byte-compile form)
|
|
|
|
|
(byte-compile
|
|
|
|
|
`(with-suppressed-warnings ,suppress ,form))))))
|
|
|
|
|
|
|
|
|
|
(ert-deftest bytecomp-test--with-suppressed-warnings ()
|
|
|
|
|
(test-suppression
|
|
|
|
|
'(defvar prefixless)
|
|
|
|
|
'((lexical prefixless))
|
|
|
|
|
"global/dynamic var .prefixless. lacks")
|
|
|
|
|
|
2022-06-06 10:47:42 +02:00
|
|
|
|
;; FIXME: These messages cannot be suppressed reliably right now,
|
|
|
|
|
;; but attempting mutate `nil' or `5' is a rather daft thing to do
|
|
|
|
|
;; in the first place. Preventing mutation of constants such as
|
|
|
|
|
;; `most-positive-fixnum' makes more sense but the compiler doesn't
|
|
|
|
|
;; warn about that at all right now (it's caught at runtime, and we
|
|
|
|
|
;; allow writing the same value).
|
|
|
|
|
;;
|
|
|
|
|
;; (test-suppression
|
|
|
|
|
;; '(defun foo()
|
|
|
|
|
;; (let ((nil t))
|
|
|
|
|
;; (message-mail)))
|
|
|
|
|
;; '((constants nil))
|
|
|
|
|
;; "Warning: attempt to let-bind constant .nil.")
|
2019-06-12 15:59:19 +02:00
|
|
|
|
|
|
|
|
|
(test-suppression
|
|
|
|
|
'(progn
|
|
|
|
|
(defun obsolete ()
|
|
|
|
|
(declare (obsolete foo "22.1")))
|
|
|
|
|
(defun zot ()
|
|
|
|
|
(obsolete)))
|
|
|
|
|
'((obsolete obsolete))
|
|
|
|
|
"Warning: .obsolete. is an obsolete function")
|
|
|
|
|
|
|
|
|
|
(test-suppression
|
|
|
|
|
'(progn
|
|
|
|
|
(defun wrong-params (foo &optional unused)
|
|
|
|
|
(ignore unused)
|
|
|
|
|
foo)
|
|
|
|
|
(defun zot ()
|
|
|
|
|
(wrong-params 1 2 3)))
|
|
|
|
|
'((callargs wrong-params))
|
2022-05-22 20:16:01 +02:00
|
|
|
|
"Warning: .wrong-params. called with")
|
2019-06-12 15:59:19 +02:00
|
|
|
|
|
|
|
|
|
(test-byte-comp-compile-and-load nil
|
|
|
|
|
(defvar obsolete-variable nil)
|
|
|
|
|
(make-obsolete-variable 'obsolete-variable nil "24.1"))
|
|
|
|
|
(test-suppression
|
|
|
|
|
'(defun zot ()
|
|
|
|
|
obsolete-variable)
|
|
|
|
|
'((obsolete obsolete-variable))
|
|
|
|
|
"obsolete")
|
|
|
|
|
|
2020-11-22 03:24:26 +01:00
|
|
|
|
(test-suppression
|
|
|
|
|
'(defun zot ()
|
|
|
|
|
(next-line))
|
|
|
|
|
'((interactive-only next-line))
|
|
|
|
|
"interactive use only")
|
|
|
|
|
|
2019-06-12 15:59:19 +02:00
|
|
|
|
(test-suppression
|
|
|
|
|
'(defun zot ()
|
|
|
|
|
(mapcar #'list '(1 2 3))
|
|
|
|
|
nil)
|
|
|
|
|
'((mapcar mapcar))
|
|
|
|
|
"Warning: .mapcar. called for effect")
|
|
|
|
|
|
|
|
|
|
(test-suppression
|
|
|
|
|
'(defun zot ()
|
|
|
|
|
free-variable)
|
|
|
|
|
'((free-vars free-variable))
|
|
|
|
|
"Warning: reference to free variable")
|
|
|
|
|
|
|
|
|
|
(test-suppression
|
|
|
|
|
'(defun zot ()
|
|
|
|
|
(save-excursion
|
|
|
|
|
(set-buffer (get-buffer-create "foo"))
|
|
|
|
|
nil))
|
|
|
|
|
'((suspicious set-buffer))
|
|
|
|
|
"Warning: Use .with-current-buffer. rather than"))
|
|
|
|
|
|
2020-12-13 17:13:50 +01:00
|
|
|
|
(ert-deftest bytecomp-tests--not-writable-directory ()
|
|
|
|
|
"Test that byte compilation works if the output directory isn't
|
|
|
|
|
writable (Bug#44631)."
|
2021-11-08 01:21:06 +01:00
|
|
|
|
(ert-with-temp-directory directory
|
|
|
|
|
(let* ((input-file (expand-file-name "test.el" directory))
|
|
|
|
|
(output-file (expand-file-name "test.elc" directory))
|
|
|
|
|
(byte-compile-dest-file-function
|
|
|
|
|
(lambda (_) output-file))
|
|
|
|
|
(byte-compile-error-on-warn t))
|
2021-11-09 05:28:48 +01:00
|
|
|
|
(unwind-protect
|
|
|
|
|
(progn
|
|
|
|
|
(write-region "" nil input-file nil nil nil 'excl)
|
|
|
|
|
(write-region "" nil output-file nil nil nil 'excl)
|
|
|
|
|
(set-file-modes input-file #o400)
|
|
|
|
|
(set-file-modes output-file #o200)
|
|
|
|
|
(set-file-modes directory #o500)
|
|
|
|
|
(should (byte-compile-file input-file))
|
|
|
|
|
(should (file-regular-p output-file))
|
|
|
|
|
(should (cl-plusp (file-attribute-size
|
|
|
|
|
(file-attributes output-file)))))
|
|
|
|
|
;; Allow the directory to be deleted.
|
|
|
|
|
(set-file-modes directory #o777)))))
|
2020-12-13 17:13:50 +01:00
|
|
|
|
|
|
|
|
|
(ert-deftest bytecomp-tests--dest-mountpoint ()
|
|
|
|
|
"Test that byte compilation works if the destination file is a
|
|
|
|
|
mountpoint (Bug#44631)."
|
|
|
|
|
(let ((bwrap (executable-find "bwrap"))
|
|
|
|
|
(emacs (expand-file-name invocation-name invocation-directory)))
|
|
|
|
|
(skip-unless bwrap)
|
|
|
|
|
(skip-unless (file-executable-p bwrap))
|
|
|
|
|
(skip-unless (not (file-remote-p bwrap)))
|
|
|
|
|
(skip-unless (file-executable-p emacs))
|
|
|
|
|
(skip-unless (not (file-remote-p emacs)))
|
2021-11-08 01:21:06 +01:00
|
|
|
|
(ert-with-temp-directory directory
|
|
|
|
|
(let* ((input-file (expand-file-name "test.el" directory))
|
|
|
|
|
(output-file (expand-file-name "test.elc" directory))
|
|
|
|
|
(unquoted-file (file-name-unquote output-file))
|
|
|
|
|
(byte-compile-dest-file-function
|
|
|
|
|
(lambda (_) output-file))
|
|
|
|
|
(byte-compile-error-on-warn t))
|
|
|
|
|
(should-not (file-remote-p input-file))
|
|
|
|
|
(should-not (file-remote-p output-file))
|
|
|
|
|
(write-region "" nil input-file nil nil nil 'excl)
|
|
|
|
|
(write-region "" nil output-file nil nil nil 'excl)
|
2021-11-09 05:28:48 +01:00
|
|
|
|
(unwind-protect
|
|
|
|
|
(progn
|
|
|
|
|
(set-file-modes input-file #o400)
|
|
|
|
|
(set-file-modes output-file #o200)
|
|
|
|
|
(set-file-modes directory #o500)
|
|
|
|
|
(with-temp-buffer
|
|
|
|
|
(let ((status (call-process
|
|
|
|
|
bwrap nil t nil
|
|
|
|
|
"--ro-bind" "/" "/"
|
|
|
|
|
"--bind" unquoted-file unquoted-file
|
|
|
|
|
emacs "--quick" "--batch" "--load=bytecomp"
|
|
|
|
|
(format "--eval=%S"
|
|
|
|
|
`(setq byte-compile-dest-file-function
|
|
|
|
|
(lambda (_) ,output-file)
|
|
|
|
|
byte-compile-error-on-warn t))
|
|
|
|
|
"--funcall=batch-byte-compile" input-file)))
|
|
|
|
|
(unless (eql status 0)
|
|
|
|
|
(ert-fail `((status . ,status)
|
|
|
|
|
(output . ,(buffer-string)))))))
|
|
|
|
|
(should (file-regular-p output-file))
|
|
|
|
|
(should (cl-plusp (file-attribute-size
|
|
|
|
|
(file-attributes output-file)))))
|
|
|
|
|
;; Allow the directory to be deleted.
|
|
|
|
|
(set-file-modes directory #o777))))))
|
2020-12-13 17:13:50 +01:00
|
|
|
|
|
2020-12-17 12:06:15 +01:00
|
|
|
|
(ert-deftest bytecomp-tests--target-file-no-directory ()
|
|
|
|
|
"Check that Bug#45287 is fixed."
|
2021-11-08 01:21:06 +01:00
|
|
|
|
(ert-with-temp-directory directory
|
|
|
|
|
(let* ((default-directory directory)
|
|
|
|
|
(byte-compile-dest-file-function (lambda (_) "test.elc"))
|
|
|
|
|
(byte-compile-error-on-warn t))
|
|
|
|
|
(write-region "" nil "test.el" nil nil nil 'excl)
|
|
|
|
|
(should (byte-compile-file "test.el"))
|
|
|
|
|
(should (file-regular-p "test.elc"))
|
|
|
|
|
(should (cl-plusp (file-attribute-size
|
|
|
|
|
(file-attributes "test.elc")))))))
|
2020-12-17 12:06:15 +01:00
|
|
|
|
|
2021-02-10 14:26:49 +01:00
|
|
|
|
(defun bytecomp-tests--get-vars ()
|
|
|
|
|
(list (ignore-errors (symbol-value 'bytecomp-tests--var1))
|
|
|
|
|
(ignore-errors (symbol-value 'bytecomp-tests--var2))))
|
|
|
|
|
|
|
|
|
|
(ert-deftest bytecomp-local-defvar ()
|
|
|
|
|
"Check that local `defvar' declarations work correctly, both
|
|
|
|
|
interpreted and compiled."
|
|
|
|
|
(let ((lexical-binding t))
|
|
|
|
|
(let ((fun '(lambda ()
|
|
|
|
|
(defvar bytecomp-tests--var1)
|
|
|
|
|
(let ((bytecomp-tests--var1 'a) ; dynamic
|
|
|
|
|
(bytecomp-tests--var2 'b)) ; still lexical
|
|
|
|
|
(ignore bytecomp-tests--var2) ; avoid warning
|
|
|
|
|
(bytecomp-tests--get-vars)))))
|
|
|
|
|
(should (listp fun)) ; Guard against overzealous refactoring!
|
|
|
|
|
(should (equal (funcall (eval fun t)) '(a nil)))
|
|
|
|
|
(should (equal (funcall (byte-compile fun)) '(a nil)))
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
;; `progn' does not constitute a lexical scope for `defvar' (bug#46387).
|
|
|
|
|
(let ((fun '(lambda ()
|
|
|
|
|
(progn
|
|
|
|
|
(defvar bytecomp-tests--var1)
|
|
|
|
|
(defvar bytecomp-tests--var2))
|
|
|
|
|
(let ((bytecomp-tests--var1 'c)
|
|
|
|
|
(bytecomp-tests--var2 'd))
|
|
|
|
|
(bytecomp-tests--get-vars)))))
|
|
|
|
|
(should (listp fun))
|
|
|
|
|
(should (equal (funcall (eval fun t)) '(c d)))
|
|
|
|
|
(should (equal (funcall (byte-compile fun)) '(c d))))))
|
|
|
|
|
|
2021-02-28 19:43:09 +00:00
|
|
|
|
(ert-deftest bytecomp-reify-function ()
|
|
|
|
|
"Check that closures that modify their bound variables are
|
|
|
|
|
compiled correctly."
|
|
|
|
|
(cl-letf ((lexical-binding t)
|
|
|
|
|
((symbol-function 'counter) nil))
|
|
|
|
|
(let ((x 0))
|
|
|
|
|
(defun counter () (cl-incf x))
|
|
|
|
|
(should (equal (counter) 1))
|
|
|
|
|
(should (equal (counter) 2))
|
|
|
|
|
;; byte compiling should not cause counter to always return the
|
|
|
|
|
;; same value (bug#46834)
|
|
|
|
|
(byte-compile 'counter)
|
|
|
|
|
(should (equal (counter) 3))
|
|
|
|
|
(should (equal (counter) 4)))
|
|
|
|
|
(let ((x 0))
|
|
|
|
|
(let ((x 1))
|
|
|
|
|
(defun counter () x)
|
|
|
|
|
(should (equal (counter) 1))
|
|
|
|
|
;; byte compiling should not cause the outer binding to shadow
|
|
|
|
|
;; the inner one (bug#46834)
|
|
|
|
|
(byte-compile 'counter)
|
|
|
|
|
(should (equal (counter) 1))))))
|
|
|
|
|
|
2021-03-09 11:04:03 -05:00
|
|
|
|
(ert-deftest bytecomp-string-vs-docstring ()
|
|
|
|
|
;; Don't confuse a string return value for a docstring.
|
|
|
|
|
(let ((lexical-binding t))
|
|
|
|
|
(should (equal (funcall (byte-compile '(lambda (x) "foo")) 'dummy) "foo"))))
|
|
|
|
|
|
2021-04-07 11:31:07 +02:00
|
|
|
|
(ert-deftest bytecomp-condition-case-success ()
|
|
|
|
|
;; No error, no success handler.
|
|
|
|
|
(should (equal (condition-case x
|
|
|
|
|
(list 42)
|
|
|
|
|
(error (cons 'bad x)))
|
|
|
|
|
'(42)))
|
|
|
|
|
;; Error, no success handler.
|
|
|
|
|
(should (equal (condition-case x
|
|
|
|
|
(/ 1 0)
|
|
|
|
|
(error (cons 'bad x)))
|
|
|
|
|
'(bad arith-error)))
|
|
|
|
|
;; No error, success handler.
|
|
|
|
|
(should (equal (condition-case x
|
|
|
|
|
(list 42)
|
|
|
|
|
(error (cons 'bad x))
|
|
|
|
|
(:success (cons 'good x)))
|
|
|
|
|
'(good 42)))
|
|
|
|
|
;; Error, success handler.
|
|
|
|
|
(should (equal (condition-case x
|
|
|
|
|
(/ 1 0)
|
|
|
|
|
(error (cons 'bad x))
|
|
|
|
|
(:success (cons 'good x)))
|
|
|
|
|
'(bad arith-error)))
|
|
|
|
|
;; Verify that the success code is not subject to the error handlers.
|
|
|
|
|
(should-error (condition-case x
|
|
|
|
|
(list 42)
|
|
|
|
|
(error (cons 'bad x))
|
|
|
|
|
(:success (/ (car x) 0)))
|
|
|
|
|
:type 'arith-error)
|
|
|
|
|
;; Check variable scoping.
|
|
|
|
|
(let ((x 2))
|
|
|
|
|
(should (equal (condition-case x
|
|
|
|
|
(list x)
|
|
|
|
|
(error (list 'bad x))
|
|
|
|
|
(:success (list 'good x)))
|
|
|
|
|
'(good (2))))
|
|
|
|
|
(should (equal (condition-case x
|
|
|
|
|
(/ 1 0)
|
|
|
|
|
(error (list 'bad x))
|
|
|
|
|
(:success (list 'good x)))
|
|
|
|
|
'(bad (arith-error)))))
|
|
|
|
|
;; Check capture of mutated result variable.
|
|
|
|
|
(should (equal (funcall
|
|
|
|
|
(condition-case x
|
|
|
|
|
3
|
|
|
|
|
(:success (prog1 (lambda (y) (+ y x))
|
|
|
|
|
(setq x 10))))
|
|
|
|
|
4)
|
|
|
|
|
14))
|
|
|
|
|
;; Check for-effect context, on error.
|
|
|
|
|
(should (equal (let ((f (lambda (x)
|
|
|
|
|
(condition-case nil
|
|
|
|
|
(/ 1 0)
|
|
|
|
|
(error 'bad)
|
|
|
|
|
(:success 'good))
|
|
|
|
|
(1+ x))))
|
|
|
|
|
(funcall f 3))
|
|
|
|
|
4))
|
|
|
|
|
;; Check for-effect context, on success.
|
|
|
|
|
(should (equal (let ((f (lambda (x)
|
|
|
|
|
(condition-case nil
|
|
|
|
|
nil
|
|
|
|
|
(error 'bad)
|
|
|
|
|
(:success 'good))
|
|
|
|
|
(1+ x))))
|
|
|
|
|
(funcall f 3))
|
|
|
|
|
4)))
|
|
|
|
|
|
2021-05-27 14:03:14 +02:00
|
|
|
|
(declare-function bc-test-alpha-f (ert-resource-file "bc-test-alpha.el"))
|
|
|
|
|
|
|
|
|
|
(ert-deftest bytecomp-defsubst ()
|
|
|
|
|
;; Check that lexical variables don't leak into inlined code. See
|
|
|
|
|
;; https://lists.gnu.org/archive/html/emacs-devel/2021-05/msg01227.html
|
|
|
|
|
|
|
|
|
|
;; First, remove any trace of the functions and package defined:
|
|
|
|
|
(fmakunbound 'bc-test-alpha-f)
|
|
|
|
|
(fmakunbound 'bc-test-beta-f)
|
|
|
|
|
(setq features (delq 'bc-test-beta features))
|
|
|
|
|
;; Byte-compile one file that uses a function from another file that isn't
|
|
|
|
|
;; compiled.
|
|
|
|
|
(let ((file (ert-resource-file "bc-test-alpha.el"))
|
|
|
|
|
(load-path (cons (ert-resource-directory) load-path)))
|
|
|
|
|
(byte-compile-file file)
|
|
|
|
|
(load-file (concat file "c"))
|
|
|
|
|
(should (equal (bc-test-alpha-f 'a) '(nil a)))))
|
|
|
|
|
|
2021-09-24 17:45:37 +02:00
|
|
|
|
(ert-deftest bytecomp-tests-byte-compile--wide-docstring-p/func-arg-list ()
|
|
|
|
|
(should-not (byte-compile--wide-docstring-p "\
|
|
|
|
|
\(dbus-register-property BUS SERVICE PATH INTERFACE PROPERTY ACCESS \
|
|
|
|
|
[TYPE] VALUE &optional EMITS-SIGNAL DONT-REGISTER-SERVICE)" fill-column))
|
|
|
|
|
(should-not (byte-compile--wide-docstring-p "\
|
|
|
|
|
(fn CMD FLAGS FIS &key (BUF (cvs-temp-buffer)) DONT-CHANGE-DISC CVSARGS \
|
|
|
|
|
POSTPROC)" fill-column))
|
|
|
|
|
;; Bug#49007
|
|
|
|
|
(should-not (byte-compile--wide-docstring-p "\
|
|
|
|
|
(fn (THIS rudel-protocol-backend) TRANSPORT \
|
|
|
|
|
INFO INFO-CALLBACK &optional PROGRESS-CALLBACK)" fill-column))
|
|
|
|
|
(should-not (byte-compile--wide-docstring-p "\
|
|
|
|
|
\(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] \
|
|
|
|
|
[:tags \\='(TAG...)] BODY...)" fill-column))
|
|
|
|
|
(should-not (byte-compile--wide-docstring-p "\
|
2021-09-30 17:08:46 +02:00
|
|
|
|
(make-soap-xs-element &key NAME NAMESPACE-TAG ID TYPE^ OPTIONAL? MULTIPLE? \
|
2021-09-24 17:45:37 +02:00
|
|
|
|
REFERENCE SUBSTITUTION-GROUP ALTERNATIVES IS-GROUP)" fill-column))
|
|
|
|
|
(should-not (byte-compile--wide-docstring-p "\
|
|
|
|
|
(fn NAME FIXTURE INPUT &key SKIP-PAIR-STRING EXPECTED-STRING \
|
|
|
|
|
EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \
|
|
|
|
|
(TEST-IN-COMMENTS t) (TEST-IN-STRINGS t) (TEST-IN-CODE t) \
|
|
|
|
|
(FIXTURE-FN \\='#\\='electric-pair-mode))" fill-column)))
|
|
|
|
|
|
2022-05-11 12:51:11 +02:00
|
|
|
|
(defun test-bytecomp-defgroup-choice ()
|
|
|
|
|
(should-not (byte-compile--suspicious-defcustom-choice 'integer))
|
|
|
|
|
(should-not (byte-compile--suspicious-defcustom-choice
|
|
|
|
|
'(choice (const :tag "foo" bar))))
|
|
|
|
|
(should (byte-compile--suspicious-defcustom-choice
|
|
|
|
|
'(choice (const :tag "foo" 'bar)))))
|
2021-09-24 17:45:37 +02:00
|
|
|
|
|
2022-06-08 10:03:55 +02:00
|
|
|
|
(ert-deftest bytecomp-function-attributes ()
|
|
|
|
|
;; Check that `byte-compile' keeps the declarations, interactive spec and
|
|
|
|
|
;; doc string of the function (bug#55830).
|
|
|
|
|
(let ((fname 'bytecomp-test-fun))
|
|
|
|
|
(fset fname nil)
|
|
|
|
|
(put fname 'pure nil)
|
|
|
|
|
(put fname 'lisp-indent-function nil)
|
|
|
|
|
(eval `(defun ,fname (x)
|
|
|
|
|
"tata"
|
|
|
|
|
(declare (pure t) (indent 1))
|
|
|
|
|
(interactive "P")
|
|
|
|
|
(list 'toto x))
|
|
|
|
|
t)
|
|
|
|
|
(let ((bc (byte-compile fname)))
|
|
|
|
|
(should (byte-code-function-p bc))
|
|
|
|
|
(should (equal (funcall bc 'titi) '(toto titi)))
|
|
|
|
|
(should (equal (aref bc 5) "P"))
|
|
|
|
|
(should (equal (get fname 'pure) t))
|
|
|
|
|
(should (equal (get fname 'lisp-indent-function) 1))
|
|
|
|
|
(should (equal (aref bc 4) "tata\n\n(fn X)")))))
|
|
|
|
|
|
2022-06-17 17:06:05 +02:00
|
|
|
|
(ert-deftest bytecomp-fun-attr-warn ()
|
|
|
|
|
;; Check that warnings are emitted when doc strings, `declare' and
|
|
|
|
|
;; `interactive' forms don't come in the proper order, or more than once.
|
|
|
|
|
(let* ((filename "fun-attr-warn.el")
|
|
|
|
|
(el (ert-resource-file filename))
|
|
|
|
|
(elc (concat el "c"))
|
|
|
|
|
(text-quoting-style 'grave))
|
|
|
|
|
(with-current-buffer (get-buffer-create "*Compile-Log*")
|
|
|
|
|
(let ((inhibit-read-only t))
|
|
|
|
|
(erase-buffer))
|
|
|
|
|
(byte-compile-file el)
|
|
|
|
|
(let ((expected
|
|
|
|
|
'("70:4: Warning: `declare' after `interactive'"
|
|
|
|
|
"74:4: Warning: Doc string after `interactive'"
|
|
|
|
|
"79:4: Warning: Doc string after `interactive'"
|
|
|
|
|
"84:4: Warning: Doc string after `declare'"
|
|
|
|
|
"89:4: Warning: Doc string after `declare'"
|
|
|
|
|
"96:4: Warning: `declare' after `interactive'"
|
|
|
|
|
"102:4: Warning: `declare' after `interactive'"
|
|
|
|
|
"108:4: Warning: `declare' after `interactive'"
|
|
|
|
|
"106:4: Warning: Doc string after `interactive'"
|
|
|
|
|
"114:4: Warning: `declare' after `interactive'"
|
|
|
|
|
"112:4: Warning: Doc string after `interactive'"
|
|
|
|
|
"118:4: Warning: Doc string after `interactive'"
|
|
|
|
|
"119:4: Warning: `declare' after `interactive'"
|
|
|
|
|
"124:4: Warning: Doc string after `interactive'"
|
|
|
|
|
"125:4: Warning: `declare' after `interactive'"
|
|
|
|
|
"130:4: Warning: Doc string after `declare'"
|
|
|
|
|
"136:4: Warning: Doc string after `declare'"
|
|
|
|
|
"142:4: Warning: Doc string after `declare'"
|
|
|
|
|
"148:4: Warning: Doc string after `declare'"
|
|
|
|
|
"159:4: Warning: More than one doc string"
|
|
|
|
|
"165:4: Warning: More than one doc string"
|
|
|
|
|
"171:4: Warning: More than one doc string"
|
|
|
|
|
"178:4: Warning: More than one doc string"
|
|
|
|
|
"186:4: Warning: More than one doc string"
|
|
|
|
|
"192:4: Warning: More than one doc string"
|
|
|
|
|
"200:4: Warning: More than one doc string"
|
|
|
|
|
"206:4: Warning: More than one doc string"
|
|
|
|
|
"215:4: Warning: More than one `declare' form"
|
|
|
|
|
"222:4: Warning: More than one `declare' form"
|
|
|
|
|
"230:4: Warning: More than one `declare' form"
|
|
|
|
|
"237:4: Warning: More than one `declare' form"
|
|
|
|
|
"244:4: Warning: More than one `interactive' form"
|
|
|
|
|
"251:4: Warning: More than one `interactive' form"
|
|
|
|
|
"258:4: Warning: More than one `interactive' form"
|
|
|
|
|
"257:4: Warning: `declare' after `interactive'"
|
|
|
|
|
"265:4: Warning: More than one `interactive' form"
|
|
|
|
|
"264:4: Warning: `declare' after `interactive'")))
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(let ((actual nil))
|
|
|
|
|
(while (re-search-forward
|
|
|
|
|
(rx bol (* (not ":")) ":"
|
|
|
|
|
(group (+ digit) ":" (+ digit) ": Warning: "
|
|
|
|
|
(or "More than one " (+ nonl) " form"
|
|
|
|
|
(: (+ nonl) " after " (+ nonl))))
|
|
|
|
|
eol)
|
|
|
|
|
nil t)
|
|
|
|
|
(push (match-string 1) actual))
|
|
|
|
|
(setq actual (nreverse actual))
|
|
|
|
|
(should (equal actual expected)))))))
|
|
|
|
|
|
|
|
|
|
|
2011-02-14 16:21:42 -05:00
|
|
|
|
;; Local Variables:
|
|
|
|
|
;; no-byte-compile: t
|
|
|
|
|
;; End:
|
2008-11-30 05:57:33 +00:00
|
|
|
|
|
2016-09-24 12:01:44 +03:00
|
|
|
|
(provide 'bytecomp-tests)
|
2021-09-26 01:53:56 +02:00
|
|
|
|
;;; bytecomp-tests.el ends here
|