1 ;;;; This file is for compiler tests which have side effects (e.g.
2 ;;;; executing DEFUN) but which don't need any special side-effecting
3 ;;;; environmental stuff (e.g. DECLAIM of particular optimization
4 ;;;; settings). Similar tests which *do* expect special settings may
5 ;;;; be in files compiler-1.impure.lisp, compiler-2.impure.lisp, etc.
7 ;;;; This software is part of the SBCL system. See the README file for
10 ;;;; While most of SBCL is derived from the CMU CL system, the test
11 ;;;; files (like this one) were written from scratch after the fork
14 ;;;; This software is in the public domain and is provided with
15 ;;;; absolutely no warranty. See the COPYING and CREDITS files for
16 ;;;; more information.
18 (when (eq sb-ext:*evaluator-mode* :interpret)
19 (sb-ext:quit :unix-status 104))
21 (load "test-util.lisp")
22 (load "assertoid.lisp")
23 (use-package "TEST-UTIL")
24 (use-package "ASSERTOID")
26 ;;; Old CMU CL code assumed that the names of "keyword" arguments are
27 ;;; necessarily self-evaluating symbols, but ANSI Common Lisp allows
28 ;;; them to be any symbols, not necessarily keywords, and thus not
29 ;;; necessarily self-evaluating. Make sure that this works.
30 (defun newfangled-cons (&key ((left-thing x)) ((right-thing y)))
32 (assert (equal (cons 1 2) (newfangled-cons 'right-thing 2 'left-thing 1)))
34 ;;; ANSI specifically says that duplicate keys are OK in lambda lists,
35 ;;; with no special exception for macro lambda lists. (As reported by
36 ;;; Pierre Mai on cmucl-imp 2001-03-30, Python didn't think so. The
37 ;;; rest of the thread had some entertainment value, at least for me
38 ;;; (WHN). The unbelievers were besmote and now even CMU CL will
39 ;;; conform to the spec in this regard. Who needs diplomacy when you
40 ;;; have brimstone?:-)
41 (defmacro ayup-duplicate-keys-are-ok-i-see-the-lite (&key k)
43 (assert (equal (ayup-duplicate-keys-are-ok-i-see-the-lite :k 112) 112))
44 (assert (equal (ayup-duplicate-keys-are-ok-i-see-the-lite :k 'x :k 'y) 'x))
46 ;;; As reported by Alexey Dejneka (sbcl-devel 2002-01-30), in
47 ;;; sbcl-0.7.1 plus his patch (i.e. essentially sbcl-0.7.1.2), the
48 ;;; compiler barfed on this, blowing up in FIND-IN-PHYSENV looking for
49 ;;; the LAMBDA-VAR named NUM. That was fixed in sbcl-0.7.1.3.
50 (defun parse-num (index)
57 (when (and (digs) (digs)) x))))
59 ;;; Bug 132: The compiler used to fail to compile INTEGER-valued CATCH
60 ;;; tags. This was fixed by Alexey Dejneka in sbcl-0.7.1.14. (INTEGER
61 ;;; catch tags are still a bad idea because EQ is used to compare
62 ;;; tags, and EQ comparison on INTEGERs is unportable; but now it's a
63 ;;; compiler warning instead of a failure to compile.)
65 (catch 0 (print 1331)))
67 ;;; Bug 150: In sbcl-0.7.1.15, compiling this code caused a failure in
68 ;;; SB-C::ADD-TEST-CONSTRAINTS:
69 ;;; The value NIL is not of type SB-C::CONTINUATION.
70 ;;; This bug was fixed by APD in sbcl-0.7.1.30.
71 (defun bug150-test1 ()
73 (flet ((wufn () (glorp table1 4.9)))
74 (gleep *uustk* #'wufn "#1" (list)))
75 (if (eql (lo foomax 3.2))
77 (error "not ~S" '(eql (lo foomax 3.2))))
79 ;;; A simpler test case for bug 150: The compiler died with the
80 ;;; same type error when trying to compile this.
81 (defun bug150-test2 ()
85 ;;; bug 147, fixed by APD 2002-04-28
87 ;;; This test case used to crash the compiler, e.g. with
88 ;;; failed AVER: "(= (LENGTH (BLOCK-SUCC CALL-BLOCK)) 1)"
89 (defun bug147 (string ind)
93 (typep (char string ind) '(member #\1)))
96 ;;; bug reported and fixed by Matthias Hoelzl sbcl-devel 2002-05-13
97 (defmacro foo-2002-05-13 () ''x)
98 (eval '(foo-2002-05-13))
99 (compile 'foo-2002-05-13)
100 (foo-2002-05-13) ; (The bug caused UNDEFINED-FUNCTION to be signalled here.)
102 ;;; floating point pain on the PPC.
104 ;;; This test case used to fail to compile on most powerpcs prior to
105 ;;; sbcl-0.7.4.2x, as floating point traps were being incorrectly
107 (defun floating-point-pain (x)
108 (declare (single-float x))
111 ;;; bug found and fixed ca. sbcl-0.7.5.12: The INTERSECTION-TYPE
112 ;;; here satisfies "is a subtype of ARRAY-TYPE", but can't be
113 ;;; accessed with ARRAY-TYPE accessors like
114 ;;; ARRAY-TYPE-SPECIALIZED-ELEMENT-TYPE, so ARRAY-related
115 ;;; DEFTRANSFORMs died with TYPE-ERROR at compile time when
116 ;;; compiling the DEFUN here.
117 (defun stupid-input-to-smart-array-deftransforms-0-7-5-12 (v)
118 (declare (type (and simple-vector fwd-type-ref) v))
121 ;;; Ca. sbcl-0.7.5.15 the compiler would fail an internal consistency
122 ;;; check on this code because it expected all calls to %INSTANCE-REF
123 ;;; to be transformed away, but its expectations were dashed by perverse
124 ;;; code containing app programmer errors like this.
125 (defstruct something-known-to-be-a-struct x y)
126 (multiple-value-bind (fun warnings-p failure-p)
130 (cond (t (a4 a2 a3))))
132 (declare (type (or simple-vector null) a5 a6))
133 (something-known-to-be-a-struct-x a5))
137 (cond ((and (funcall a12 a2)
142 (let ((a15 (a1 a2 a3)))
145 (values #'a17 #'a11))))
146 ;; Python sees the structure accessor on the known-not-to-be-a-struct
147 ;; A5 value and is very, very disappointed in you. (But it doesn't
148 ;; signal BUG any more.)
151 ;;; On the SPARC, there was an erroneous definition of some VOPs used
152 ;;; to compile LOGANDs, which would lead to compilation of the
153 ;;; following function giving rise to a compile-time error (bug
154 ;;; spotted and fixed by Raymond Toy for CMUCL)
155 (defun logand-sparc-bogons (a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10)
156 (declare (type (unsigned-byte 32) a0)
157 (type (signed-byte 32) a1 a2 a3 a4 a5 a6 a7 a8 a9 a10)
158 ;; to ensure that the call is a candidate for
160 (optimize (speed 3) (safety 0) (compilation-speed 0) (debug 0)))
162 ;; the call that fails compilation
164 ;; a call to prevent the other arguments from being optimized away
165 (logand a1 a2 a3 a4 a5 a6 a7 a8 a9)))
167 ;;; bug 192, reported by Einar Floystad Dorum sbcl-devel 2002-08-14,
168 ;;; fixed in sbcl-0.7.6.26: Compiling this function in 0.7.6 caused
169 ;;; the compiler to try to constant-fold DATA-VECTOR-REF, which is OK,
170 ;;; except that there was no non-VOP definition of DATA-VECTOR-REF, so
182 (DECLARE (IGNORABLE S E))
192 (DECLARE (IGNORABLE S E))
193 (WHEN (EQL #\b E) (G910 (1+ I)))))))
200 (DECLARE (IGNORABLE S))
203 (G908 I))) "abcdefg" 0 (length "abcdefg")))
205 ;;; bugs #65, #70, and #109, closed by APD's patch sbcl-devel 2002-08-17
207 ;;; This was "YA code deletion bug" whose symptom was the failure of
209 ;;; (EQ (C::LAMBDA-TAIL-SET C::CALLER)
210 ;;; (C::LAMBDA-TAIL-SET (C::LAMBDA-HOME C::CALLEE)))
212 (defun bug65-1 (termx termy) ; from Carl Witty on submit bugs list, debian.org
214 ((alpha-equal-bound-term-lists (listx listy)
215 (or (and (null listx) (null listy))
217 (let ((bindings-x (bindings-of-bound-term (car listx)))
218 (bindings-y (bindings-of-bound-term (car listy))))
219 (if (and (null bindings-x) (null bindings-y))
220 (alpha-equal-terms (term-of-bound-term (car listx))
221 (term-of-bound-term (car listy)))
222 (and (= (length bindings-x) (length bindings-y))
224 (enter-binding-pairs (bindings-of-bound-term (car listx))
225 (bindings-of-bound-term (car listy)))
226 (alpha-equal-terms (term-of-bound-term (car listx))
227 (term-of-bound-term (car listy)))
228 (exit-binding-pairs (bindings-of-bound-term (car listx))
229 (bindings-of-bound-term (car listy)))))))
230 (alpha-equal-bound-term-lists (cdr listx) (cdr listy)))))
232 (alpha-equal-terms (termx termy)
233 (if (and (variable-p termx)
235 (equal-bindings (id-of-variable-term termx)
236 (id-of-variable-term termy))
237 (and (equal-operators-p (operator-of-term termx) (operator-of-term termy))
238 (alpha-equal-bound-term-lists (bound-terms-of-term termx)
239 (bound-terms-of-term termy))))))
243 (with-variable-invocation (alpha-equal-terms termx termy))))))
244 (defun bug65-2 () ; from Bob Rogers cmucl-imp 1999-07-28
245 ;; Given an FSSP alignment file named by the argument . . .
246 (labels ((get-fssp-char ()
250 ;; Stub body, enough to tickle the bug.
251 (list (read-fssp-char)
253 (defun bug70 ; from David Young cmucl-help 30 Nov 2000
254 (item sequence &key (test #'eql))
255 (labels ((find-item (obj seq test &optional (val nil))
256 (let ((item (first seq)))
259 ((funcall test obj item)
265 (nconc val `(,item))))))))
266 (find-item item sequence test)))
267 (defun bug109 () ; originally from CMU CL bugs collection, reported as
268 ; SBCL bug by MNA 2001-06-25
273 ;; Uncomment and it works
277 ;;; bug 192a, fixed by APD "more strict type checking" patch
278 ;;; (sbcl-devel 2002-08-07)
280 (declare (optimize (speed 0) (safety 3)))
281 ;; Even with bug 192a, this declaration was checked as an assertion.
285 ;; Because of bug 192a, this declaration was trusted without checking.
286 (declare (single-float x))
288 (assert (null (ignore-errors (bug192a nil))))
289 (multiple-value-bind (result error) (ignore-errors (bug192a 100))
290 (assert (null result))
291 (assert (equal (type-error-expected-type error) 'single-float)))
293 ;;; bug 194, fixed in part by APD "more strict type checking" patch
294 ;;; (sbcl-devel 2002-08-07)
296 (multiple-value-bind (result error)
297 (ignore-errors (multiple-value-prog1 (progn (the real '(1 2 3)))))
298 (assert (null result))
299 (assert (typep error 'type-error)))
300 (multiple-value-bind (result error)
301 (ignore-errors (the real '(1 2 3)))
302 (assert (null result))
303 (assert (typep error 'type-error))))
308 (arg2 (identity (the real #(1 2 3)))))
309 (if (< arg1 arg2) arg1 arg2)))))
310 (assert (eq (bug194d) t))
313 ;;; BUG 48a. and b. (symbol-macrolet handling), fixed by Eric Marsden
314 ;;; and Raymond Toy for CMUCL, fix ported for sbcl-0.7.6.18.
315 (multiple-value-bind (function warnings-p failure-p)
316 (compile nil '(lambda ()
317 ;; not interested in the package lock violation here
318 (declare (sb-ext:disable-package-locks t))
319 (symbol-macrolet ((t nil)) t)))
321 (assert (raises-error? (funcall function) program-error)))
322 (multiple-value-bind (function warnings-p failure-p)
325 ;; not interested in the package lock violation here
326 (declare (sb-ext:disable-package-locks *standard-input*))
327 (symbol-macrolet ((*standard-input* nil))
330 (assert (raises-error? (funcall function) program-error)))
331 (multiple-value-bind (function warnings-p failure-p)
332 (compile nil '(lambda () (symbol-macrolet ((s nil)) (declare (special s)) s)))
334 (assert (raises-error? (funcall function) program-error)))
336 ;;; bug 120a: Turned out to be constraining code looking like (if foo
337 ;;; <X> <X>) where <X> was optimized by the compiler to be the exact
338 ;;; same block in both cases, but not turned into (PROGN FOO <X>).
339 ;;; Fixed by APD in sbcl-0.7.7.2, who provided this test:
340 (declaim (inline dont-constrain-if-too-much))
341 (defun dont-constrain-if-too-much (frame up-frame)
342 (declare (optimize (speed 3) (safety 1) (debug 1)))
343 (if (or (not frame) t)
346 (defun dont-constrain-if-too-much-aux (x y)
347 (declare (optimize (speed 3) (safety 1) (debug 1)))
348 (if x t (if y t (dont-constrain-if-too-much x y))))
350 (assert (null (dont-constrain-if-too-much-aux nil nil)))
352 ;;; TYPE-ERROR confusion ca. sbcl-0.7.7.24, reported and fixed by
353 ;;; APD sbcl-devel 2002-09-14
354 (defun exercise-0-7-7-24-bug (x)
355 (declare (integer x))
357 (setf y (the single-float (if (> x 0) x 3f0)))
359 (multiple-value-bind (v e) (ignore-errors (exercise-0-7-7-24-bug 4))
361 (assert (typep e 'type-error)))
362 (assert (equal (exercise-0-7-7-24-bug -4) '(3f0 3f0)))
364 ;;; non-intersecting type declarations were DWIMing in a confusing
365 ;;; fashion until sbcl-0.7.7.28, when APD reported and fixed the
367 (defun non-intersecting-the (x)
369 (setf y (the single-float (the integer x)))
372 (raises-error? (foo 3) type-error)
373 (raises-error? (foo 3f0) type-error)
375 ;;; until 0.8.2 SBCL did not check THEs in arguments
376 (defun the-in-arguments-aux (x)
378 (defun the-in-arguments-1 (x)
379 (list x (the-in-arguments-aux (the (single-float 0s0) x))))
380 (defun the-in-arguments-2 (x)
381 (list x (the-in-arguments-aux (the single-float x))))
383 (multiple-value-bind (result condition)
384 (ignore-errors (the-in-arguments-1 1))
385 (assert (null result))
386 (assert (typep condition 'type-error)))
387 (multiple-value-bind (result condition)
388 (ignore-errors (the-in-arguments-2 1))
389 (assert (null result))
390 (assert (typep condition 'type-error)))
392 ;;; bug 153: a hole in a structure slot type checking
393 (declaim (optimize safety))
395 (bla 0 :type fixnum))
397 (let ((foo (make-foo153)))
398 (setf (foo153-bla foo) '(1 . 1))
399 (format t "Is ~a of type ~a a cons? => ~a~%"
401 (type-of (foo153-bla foo))
402 (consp (foo153-bla foo)))))
404 (let ((foo (make-foo153)))
405 (setf (foo153-bla foo) x)
406 (format t "Is ~a of type ~a a cons? => ~a~%"
408 (type-of (foo153-bla foo))
409 (consp (foo153-bla foo)))))
411 (multiple-value-bind (result condition)
412 (ignore-errors (bug153-1))
413 (declare (ignore result))
414 (assert (typep condition 'type-error)))
415 (multiple-value-bind (result condition)
416 (ignore-errors (bug153-2 '(1 . 1)))
417 (declare (ignore result))
418 (assert (typep condition 'type-error)))
420 ;;;; bug 110: the compiler flushed the argument type test and the default
421 ;;;; case in the cond.
423 ;(locally (declare (optimize (safety 3) (speed 2)))
425 ; (declare (optimize (safety 2) (speed 3)))
426 ; (declare (type (or string stream) x))
427 ; (cond ((typep x 'string) 'string)
428 ; ((typep x 'stream) 'stream)
432 ;(multiple-value-bind (result condition)
433 ; (ignore-errors (bug110 0))
434 ; (declare (ignore result))
435 ; (assert (typep condition 'type-error)))
437 ;;; bug 202: the compiler failed to compile a function, which derived
438 ;;; type contradicted declared.
439 (declaim (ftype (function () null) bug202))
443 ;;; bugs 178, 199: compiler failed to compile a call of a function
444 ;;; with a hairy type
446 (funcall (the function (the standard-object x))))
448 (defun bug199-aux (f)
449 (eq nil (funcall f)))
452 (declare (type (and function (satisfies bug199-aux)) f))
455 ;;; check non-toplevel DEFMACRO
456 (defvar *defmacro-test-status* nil)
458 (defun defmacro-test ()
459 (fmakunbound 'defmacro-test-aux)
460 (let* ((src "defmacro-test.lisp")
461 (obj (compile-file-pathname src)))
465 (assert (equal *defmacro-test-status* '(function a)))
466 (setq *defmacro-test-status* nil)
468 (assert (equal *defmacro-test-status* nil))
469 (macroexpand '(defmacro-test-aux 'a))
470 (assert (equal *defmacro-test-status* '(macro 'a z-value)))
471 (eval '(defmacro-test-aux 'a))
472 (assert (equal *defmacro-test-status* '(expanded 'a z-value))))
473 (ignore-errors (delete-file obj)))))
477 ;;; bug 204: EVAL-WHEN inside a local environment
478 (defvar *bug204-test-status*)
480 (defun bug204-test ()
481 (let* ((src "bug204-test.lisp")
482 (obj (compile-file-pathname src)))
485 (setq *bug204-test-status* nil)
487 (assert (equal *bug204-test-status* '((:expanded :load-toplevel)
488 (:called :compile-toplevel)
489 (:expanded :compile-toplevel))))
490 (setq *bug204-test-status* nil)
492 (assert (equal *bug204-test-status* '((:called :load-toplevel)))))
493 (ignore-errors (delete-file obj)))))
497 ;;; toplevel SYMBOL-MACROLET
498 (defvar *symbol-macrolet-test-status*)
500 (defun symbol-macrolet-test ()
501 (let* ((src "symbol-macrolet-test.lisp")
502 (obj (compile-file-pathname src)))
505 (setq *symbol-macrolet-test-status* nil)
507 (assert (equal *symbol-macrolet-test-status*
509 (setq *symbol-macrolet-test-status* nil)
511 (assert (equal *symbol-macrolet-test-status* '(2))))
512 (ignore-errors (delete-file obj)))))
514 (symbol-macrolet-test)
516 ;;; On the x86, this code failed to compile until sbcl-0.7.8.37:
517 (defun x86-assembler-failure (x)
518 (declare (optimize (speed 3) (safety 0)))
519 (eq (setf (car x) 'a) nil))
521 ;;; bug 211: :ALLOW-OTHER-KEYS
522 (defun bug211d (&key (x :x x-p) ((:allow-other-keys y) :y y-p))
525 (assert (equal (bug211d) '(:x nil :y nil)))
526 (assert (equal (bug211d :x 1) '(1 t :y nil)))
527 (assert (raises-error? (bug211d :y 2) program-error))
528 (assert (equal (bug211d :y 2 :allow-other-keys t :allow-other-keys nil)
530 (assert (raises-error? (bug211d :y 2 :allow-other-keys nil) program-error))
537 (flet ((test (&key (x :x x-p) ((:allow-other-keys y) :y y-p))
539 (assert (equal (test) '(:x nil :y nil)))
540 (assert (equal (test :x 1) '(1 t :y nil)))
541 (assert (equal (test :y 2 :allow-other-keys 11 :allow-other-keys nil)
542 '(:x nil 11 t)))))))))
543 (assert (not failure-p))
551 (flet ((test (&key (x :x x-p))
553 (assert (equal (test) '(:x nil)))
554 (assert (equal (test :x 1) '(1 t)))
555 (assert (equal (test :y 2 :allow-other-keys 11 :allow-other-keys nil)
557 (assert (not failure-p))
560 (dolist (form '((test :y 2)
561 (test :y 2 :allow-other-keys nil)
562 (test :y 2 :allow-other-keys nil :allow-other-keys t)))
563 (multiple-value-bind (result warnings-p failure-p)
564 (compile nil `(lambda ()
565 (flet ((test (&key (x :x x-p) ((:allow-other-keys y) :y y-p))
569 (assert (raises-error? (funcall result) program-error))))
571 ;;; bug 217: wrong type inference
572 (defun bug217-1 (x s)
573 (let ((f (etypecase x
574 (character #'write-char)
575 (integer #'write-byte))))
578 (character (write-char x s))
579 (integer (write-byte x s)))))
580 (bug217-1 #\1 *standard-output*)
583 ;;; bug 221: tried and died on CSUBTYPEP (not VALUES-SUBTYPEP) of the
584 ;;; function return types when inferring the type of the IF expression
585 (declaim (ftype (function (fixnum) (values package boolean)) bug221f1))
586 (declaim (ftype (function (t) (values package boolean)) bug221f2))
588 (funcall (if b #'bug221f1 #'bug221f2) x))
590 ;;; bug 172: macro lambda lists were too permissive until 0.7.9.28
591 ;;; (fix provided by Matthew Danish) on sbcl-devel
592 (assert (null (ignore-errors
593 (defmacro bug172 (&rest rest foo) `(list ,rest ,foo)))))
596 (defun check-embedded-thes (policy1 policy2 x y)
598 (funcall (compile nil
600 (declare (optimize (speed 2) (safety ,policy1)))
602 (the (values (integer 2 3) t &optional)
603 (locally (declare (optimize (safety ,policy2)))
604 (the (values t (single-float 2f0 3f0) &optional)
606 (lambda () (values x y)))
610 (assert (equal (check-embedded-thes 0 0 :a :b) '(:a :b)))
612 (assert (equal (check-embedded-thes 0 3 :a 2.5f0) '(:a 2.5f0)))
613 (assert (typep (check-embedded-thes 0 3 2 3.5f0) 'type-error))
615 (assert (equal (check-embedded-thes 0 1 :a 3.5f0) '(:a 3.5f0)))
616 (assert (typep (check-embedded-thes 0 1 2 2.5d0) 'type-error))
618 (assert (equal (check-embedded-thes 3 0 2 :a) '(2 :a)))
619 (assert (typep (check-embedded-thes 3 0 4 2.5f0) 'type-error))
621 (assert (equal (check-embedded-thes 1 0 4 :b) '(4 :b)))
622 (assert (typep (check-embedded-thes 1 0 1.0 2.5f0) 'type-error))
625 (assert (equal (check-embedded-thes 3 3 2 2.5f0) '(2 2.5f0)))
626 (assert (typep (check-embedded-thes 3 3 0 2.5f0) 'type-error))
627 (assert (typep (check-embedded-thes 3 3 2 3.5f0) 'type-error))
629 ;;; INLINE inside MACROLET
630 (declaim (inline to-be-inlined))
631 (macrolet ((def (x) `(defun ,x (y) (+ y 1))))
633 (defun call-inlined (z)
635 (assert (= (call-inlined 3) 4))
636 (macrolet ((frob (x) `(+ ,x 3)))
637 (defun to-be-inlined (y)
639 (assert (= (call-inlined 3)
640 ;; we should have inlined the previous definition, so the
641 ;; new one won't show up yet.
643 (defun call-inlined (z)
645 (assert (= (call-inlined 3) 6))
646 (defun to-be-inlined (y)
648 (assert (= (call-inlined 3) 6))
650 ;;; DEFINE-COMPILER-MACRO to work as expected, not via weird magical
651 ;;; IR1 pseudo-:COMPILE-TOPLEVEL handling
652 (defvar *bug219-a-expanded-p* nil)
655 (define-compiler-macro bug219-a (&whole form y)
656 (setf *bug219-a-expanded-p* t)
660 (defun bug219-a-aux ()
662 (assert (= (bug219-a-aux)
663 (if *bug219-a-expanded-p* 4 3)))
664 (defvar *bug219-a-temp* 3)
665 (assert (= (bug219-a *bug219-a-temp*) 4))
667 (defvar *bug219-b-expanded-p* nil)
668 (defun bug219-b-aux1 (x)
670 (define-compiler-macro bug219-b (y)
671 (setf *bug219-b-expanded-p* t)
673 (defun bug219-b-aux2 (z)
675 (assert (not *bug219-b-expanded-p*))
676 (assert (raises-error? (bug219-b-aux2 1) undefined-function))
678 (defun bug219-b-aux2 (z)
682 (assert (= (bug219-b-aux2 1)
683 (if *bug219-b-expanded-p* 3 1)))
685 ;;; bug 224: failure in unreachable code deletion
686 (defmacro do-optimizations (&body body)
687 `(dotimes (.speed. 4)
690 (dotimes (.compilation-speed. 4)
691 (proclaim `(optimize (speed , .speed.) (space , .space.)
693 (compilation-speed , .compilation-speed.)))
699 "(lambda () (#:localy (declare (optimize (safety 3)))
700 (ignore-errors (progn (values-list (car (list '(1 . 2)))) t))))")))
703 (compile nil '(lambda ()
706 (labels ((i1 () (list (i2) (i2)))
707 (i2 () (list (int) (i1)))
709 (list (i1) (i1) (i1)))
710 :exit (return-from ext)
712 (list (error "nih") (ext) (ext))))))
715 (compile nil '(lambda (x) (let ((y (error ""))) (list x y)))))
717 ;;; bug 223: invalid moving of global function name referencing
718 (defun bug223-int (n)
721 (defun bug223-wrap ()
722 (let ((old #'bug223-int))
723 (setf (fdefinition 'bug223-int)
726 `(ext ,@(funcall old (1- n)))))))
727 (compile 'bug223-wrap)
729 (assert (equal (bug223-int 4) '(int 4)))
731 (assert (equal (bug223-int 4) '(ext int 3)))
733 (assert (equal (bug223-int 4) '(ext ext int 2)))
735 ;;; COERCE got its own DEFOPTIMIZER which has to reimplement most of
736 ;;; SPECIFIER-TYPE-NTH-ARG. For a while, an illegal type would throw
737 ;;; you into the debugger on compilation.
738 (defun coerce-defopt1 (x)
739 ;; illegal, but should be compilable.
740 (coerce x '(values t)))
741 (defun coerce-defopt2 (x)
742 ;; illegal, but should be compilable.
743 (coerce x '(values t &optional)))
744 (assert (null (ignore-errors (coerce-defopt1 3))))
745 (assert (null (ignore-errors (coerce-defopt2 3))))
747 ;;; Oops. In part of the (CATCH ..) implementation of DEBUG-RETURN,
748 ;;; it was possible to confuse the type deriver of the compiler
749 ;;; sufficiently that compiler invariants were broken (explained by
750 ;;; APD sbcl-devel 2003-01-11).
752 ;;; WHN's original report
753 (defun debug-return-catch-break1 ()
754 (with-open-file (s "/tmp/foo"
759 (integer-length most-positive-fixnum))))
765 ;;; APD's simplified test case
766 (defun debug-return-catch-break2 (x)
767 (declare (type (vector (unsigned-byte 8)) x))
768 (setq *y* (the (unsigned-byte 8) (aref x 4))))
770 ;;; FUNCTION-LAMBDA-EXPRESSION should return something that's COMPILE
771 ;;; can understand. Here's a simple test for that on a function
772 ;;; that's likely to return a hairier list than just a lambda:
773 (macrolet ((def (fn) `(progn
774 (declaim (inline ,fn))
775 (defun ,fn (x) (1+ x)))))
777 (let ((x (function-lambda-expression #'bug228)))
779 (assert (= (funcall (compile nil x) 1) 2))))
784 (declare (type (mod 4) i))
787 (assert (raises-error? (bug192b 6) type-error))
790 (locally (declare (type fixnum x y))
792 (assert (raises-error? (bug192c 1.1 2) type-error))
794 (assert (raises-error? (progn (the real (list 1)) t) type-error))
797 (declare (optimize (speed 2) (safety 0)))
800 (multiple-value-prog1
802 (unless f (return-from bug236 0))))))
803 (assert (eql (bug236 #(4) nil) 0))
805 ;;; Bug reported by reported by rif on c.l.l 2003-03-05
806 (defun test-type-of-special-1 (x)
809 (optimize (safety 3)))
811 (defun test-type-of-special-2 (x)
814 (optimize (safety 3)))
815 (list x (setq x (/ x 2)) x))
816 (assert (raises-error? (test-type-of-special-1 3/2) type-error))
817 (assert (raises-error? (test-type-of-special-2 3) type-error))
818 (assert (equal (test-type-of-special-2 8) '(8 4 4)))
820 ;;; bug which existed in 0.8alpha.0.4 for several milliseconds before
821 ;;; APD fixed it in 0.8alpha.0.5
822 (defun frob8alpha04 (x y)
824 (defun baz8alpha04 (this kids)
825 (flet ((n-i (&rest rest)
826 ;; Removing the #+NIL here makes the bug go away.
827 #+nil (format t "~&in N-I REST=~S~%" rest)
828 (apply #'frob8alpha04 this rest)))
830 ;;; failed in 0.8alpha.0.4 with "The value 13 is not of type LIST."
831 (assert (= (baz8alpha04 12 13) 25))
833 ;;; evaluation order in structure slot writers
837 (s (make-sswo :a (incf i) :b (incf i)))
839 (assert (= (sswo-a s) 1))
840 (assert (= (sswo-b s) 2))
841 (setf (sswo-a (pop l)) (pop l))
843 (assert (eq (sswo-a s) :v)))
849 (list (bar x) (bar x) (bar x))))
851 (assert (raises-error? (bug249 1.0) type-error))
853 ;;; bug reported by ohler on #lisp 2003-07-10
854 (defun bug-ohler-2003-07-10 (a b)
855 (declare (optimize (speed 0) (safety 3) (space 0)
856 (debug 1) (compilation-speed 0)))
859 ;;; bug reported by Doug McNaught on sbcl-devel 2003-09-14:
860 ;;; COMPILE-FILE did not bind *READTABLE*
861 (let* ((source "bug-doug-mcnaught-20030914.lisp")
862 (fasl (compile-file-pathname source)))
864 (assert (null (get-macro-character #\]))))
867 (assert (typep *bug-doug-mcnaught-20030914*
868 '(simple-array (unsigned-byte 4) (*))))
869 (assert (equalp *bug-doug-mcnaught-20030914* #(1 2 3)))
870 (makunbound '*bug-doug-mcnaught-20030914*)))
871 (compile-file source)
879 (defun expt-derive-type-bug (a b)
881 (truncate (expt a b))))
882 (assert (equal (multiple-value-list (expt-derive-type-bug 1 1))
885 ;;; Problems with type checking in functions with EXPLICIT-CHECK
886 ;;; attribute (reported by Peter Graves)
887 (loop for (fun . args) in '((= a) (/= a)
888 (< a) (<= a) (> a) (>= a))
889 do (assert (raises-error? (apply fun args) type-error)))
891 (defclass broken-input-stream (sb-gray:fundamental-input-stream) ())
892 (defmethod sb-gray:stream-read-char ((stream broken-input-stream))
893 (throw 'break :broken))
894 (assert (eql (block return
897 (funcall (eval ''peek-char)
898 1 (make-instance 'broken-input-stream))
901 (return-from return :good))))
904 ;;;; MUFFLE-CONDITIONS test (corresponds to the test in the manual)
905 (defvar *compiler-note-count* 0)
906 #-(or alpha x86-64) ; FIXME: make a better test!
907 (handler-bind ((sb-ext:compiler-note (lambda (c)
909 (incf *compiler-note-count*))))
913 (declare (optimize speed) (fixnum x))
914 (declare (sb-ext:muffle-conditions sb-ext:compiler-note))
915 (values (* x 5) ; no compiler note from this
917 (declare (sb-ext:unmuffle-conditions sb-ext:compiler-note))
918 ;; this one gives a compiler note
920 (assert (= *compiler-note-count* 1))
921 (assert (equal (multiple-value-list (funcall fun 1)) '(5 -5)))))
924 (eval '(flet ((%f (&key) nil)) (%f nil nil)))
926 (:no-error (val) (error "no error: ~S" val)))
928 (eval '(labels ((%f (&key x) x)) (%f nil nil)))
930 (:no-error (val) (error "no error: ~S" val)))
932 ;;;; tests not in the problem domain, but of the consistency of the
933 ;;;; compiler machinery itself
937 ;;; Hunt for wrong-looking things in fundamental compiler definitions,
938 ;;; and gripe about them.
940 ;;; FIXME: It should be possible to (1) repair the things that this
941 ;;; code gripes about, and then (2) make the code signal errors
942 ;;; instead of just printing complaints to standard output, in order
943 ;;; to prevent the code from later falling back into disrepair.
944 (defun grovel-results (function)
945 (dolist (template (fun-info-templates (info :function :info function)))
946 (when (template-more-results-type template)
947 (format t "~&Template ~A has :MORE results, and translates ~A.~%"
948 (template-name template)
951 (when (eq (template-result-types template) :conditional)
954 (let ((types (template-result-types template))
955 (result-type (fun-type-returns (info :function :type function))))
957 ((values-type-p result-type)
958 (do ((ltypes (append (args-type-required result-type)
959 (args-type-optional result-type))
961 (types types (rest types)))
964 (format t "~&More types than ltypes in ~A, translating ~A.~%"
965 (template-name template)
969 (unless (null ltypes)
970 (format t "~&More ltypes than types in ~A, translating ~A.~%"
971 (template-name template)
974 ((eq result-type (specifier-type nil))
976 (format t "~&Template ~A returns values for function ~A with RESULT-TYPE NIL.~%"
977 (template-name template)
980 ((/= (length types) 1)
981 (format t "~&Template ~A isn't returning 1 value for ~A.~%"
982 (template-name template)
986 (defun identify-suspect-vops (&optional (env (first
987 (last *info-environment*))))
988 (do-info (env :class class :type type :name name :value value)
989 (when (and (eq class :function) (eq type :type))
990 ;; OK, so we have an entry in the INFO database. Now, if ...
991 (let* ((info (info :function :info name))
992 (templates (and info (fun-info-templates info))))
994 ;; ... it has translators
995 (grovel-results name))))))
996 (identify-suspect-vops)
998 ;;;; tests for compiler output
999 (let* ((*error-output* (make-broadcast-stream))
1000 (output (with-output-to-string (*standard-output*)
1001 (compile-file "compiler-output-test.lisp"
1002 :print nil :verbose nil))))
1004 (assert (zerop (length output))))
1006 ;;;; bug 305: INLINE/NOTINLINE causing local ftype to be lost
1008 (define-condition optimization-error (error) ())
1010 (labels ((compile-lambda (type sense)
1011 (handler-bind ((compiler-note (lambda (_)
1012 (declare (ignore _))
1013 (error 'optimization-error))))
1019 ,@(when type '((ftype (function () (integer 0 10)) bug-305)))
1024 (expect-error (sense)
1025 (multiple-value-bind (f e) (ignore-errors (compile-lambda nil sense))
1027 (assert (typep e 'optimization-error))))
1028 (expect-pass (sense)
1029 (multiple-value-bind (f e) (ignore-errors (compile-lambda t sense))
1032 (expect-error 'inline)
1033 (expect-error 'notinline)
1034 (expect-pass 'inline)
1035 (expect-pass 'notinline))
1037 ;;; bug 211e: bogus style warning from duplicated keyword argument to
1038 ;;; a local function.
1039 (handler-bind ((style-warning #'error))
1040 (let ((f (compile nil '(lambda ()
1041 (flet ((foo (&key y) (list y)))
1042 (list (foo :y 1 :y 2)))))))
1043 (assert (equal '((1)) (funcall f)))))
1045 ;;; check that EQL is optimized when other argument is (OR SYMBOL FIXNUM).
1046 (handler-bind ((compiler-note #'error))
1047 (let ((f1 (compile nil '(lambda (x1 y1)
1048 (declare (type (or symbol fixnum) x1)
1051 (f2 (compile nil '(lambda (x2 y2)
1052 (declare (type (or symbol fixnum) y2)
1055 (let ((fix (random most-positive-fixnum))
1058 (assert (funcall f1 fix fix))
1059 (assert (funcall f2 fix fix))
1060 (assert (funcall f1 sym sym))
1061 (assert (funcall f2 sym sym))
1062 (handler-bind ((type-error (lambda (c)
1065 (flet ((test (f x y)
1066 (with-simple-restart (continue "continue with next test")
1068 (error "fell through with (~S ~S ~S)" f x y))))
1070 (test f1 (1+ most-positive-fixnum) 42)
1072 (test f2 42 (1+ most-positive-fixnum))))
1073 (assert (= e-count 4)))))
1075 ;;; bug #389 (Rick Taube sbcl-devel)
1076 (defun bes-jn (unn ux)
1077 (let ((nn unn) (x ux))
1078 (let* ((n (floor (abs nn)))
1091 (do ((tox (/ 2.0 (abs x)))
1092 (bjm (bes-j0 (abs x)))
1093 (bj (bes-j1 (abs x)))
1096 ((= j n) (setf ans bj))
1097 (setf bjp (- (* j tox bj) bjm))
1100 (let ((tox (/ 2.0 (abs x)))
1104 (/ (+ n (sqrt (* iacc n)))
1113 (setf bjm (- (* j tox bj) bjp))
1116 (when (> (abs bj) bigno)
1117 (setf bj (* bj bigni))
1118 (setf bjp (* bjp bigni))
1119 (setf ans (* ans bigni))
1120 (setf sum (* sum bigni)))
1121 (if (not (= 0 jsum)) (incf sum bj))
1122 (setf jsum (- 1 jsum))
1123 (if (= j n) (setf ans bjp)))
1124 (setf sum (- (* 2.0 sum) bj))
1125 (setf ans (/ ans sum))))
1126 (if (and (minusp x) (oddp n))
1129 (if (and (minusp nn) (oddp nn)) (- besn) besn))))
1132 ;;; bug 233b: lvar lambda-var equality in constraint propagation
1134 ;; Put this in a separate function.
1135 (defun test-constraint-propagation/ref ()
1137 (if (multiple-value-prog1 x (setq x t))
1141 (test-util:with-test (:name (:compiler :constraint-propagation :ref))
1142 (assert (eq t (test-constraint-propagation/ref))))
1144 ;; Put this in a separate function.
1145 (defun test-constraint-propagation/typep (x y)
1146 (if (typep (multiple-value-prog1 x (setq x y))
1151 (test-util:with-test (:name (:compiler :constraint-propagation :typep))
1152 (assert (= 6.0d0 (test-constraint-propagation/typep 1d0 5))))
1154 (test-util:with-test (:name (:compiler :constraint-propagation :eq/eql))
1155 (assert (eq :right (let ((c :wrong))
1156 (if (eq (let ((x c))
1163 ;;; Put this in a separate function.
1164 (defun test-constraint-propagation/cast (x)
1165 (when (the double-float (multiple-value-prog1
1170 (test-util:with-test (:name (:compiler :constraint-propagation :cast))
1171 (assert (assertoid:raises-error?
1172 (test-constraint-propagation/cast 1) type-error)))
1175 (let ((result (make-array 50000 :fill-pointer 0 :adjustable t)))
1176 (defun string->html (string &optional (max-length nil))
1177 (when (and (numberp max-length)
1178 (> max-length (array-dimension result 0)))
1179 (setf result (make-array max-length :fill-pointer 0 :adjustable t)))
1182 (labels ((add-char (it)
1183 (setf (aref result index) it)
1186 (loop for ch across it do
1188 (loop for char across string do
1189 (cond ((char= char #\<)
1190 (add-string "<"))
1192 (add-string ">"))
1194 (add-string "&"))
1196 (add-string "'"))
1197 ((char= char #\newline)
1198 (add-string "<br>"))
1200 (if left-quote? (add-string "“") (add-string "”"))
1201 (setf left-quote? (not left-quote?)))
1204 (setf (fill-pointer result) index)
1205 (coerce result 'string)))))
1207 ;;; Callign thru constant symbols
1208 (require :sb-introspect)
1210 (declaim (inline target-fun))
1211 (defun target-fun (arg0 arg1)
1213 (declaim (notinline target-fun))
1215 (defun test-target-fun-called (fun res)
1216 (assert (member #'target-fun
1217 (sb-introspect:find-function-callees #'caller-fun-1)))
1218 (assert (equal (funcall fun) res)))
1220 (defun caller-fun-1 ()
1221 (funcall 'target-fun 1 2))
1222 (test-target-fun-called #'caller-fun-1 3)
1224 (defun caller-fun-2 ()
1225 (declare (inline target-fun))
1226 (apply 'target-fun 1 '(3)))
1227 (test-target-fun-called #'caller-fun-2 4)
1229 (defun caller-fun-3 ()
1230 (flet ((target-fun (a b)
1232 (list (funcall #'target-fun 1 4) (funcall 'target-fun 1 4))))
1233 (test-target-fun-called #'caller-fun-3 (list -3 5))
1235 ;;; Reported by NIIMI Satoshi
1236 ;;; Subject: [Sbcl-devel] compilation error with optimization
1237 ;;; Date: Sun, 09 Apr 2006 17:36:05 +0900
1238 (defun test-minimal-debug-info-for-unstored-but-used-parameter (n a)
1239 (declare (optimize (speed 3)
1243 (test-minimal-debug-info-for-unstored-but-used-parameter (1- n) a)))
1245 ;;; &KEY arguments with non-constant defaults.
1246 (declaim (notinline opaque-identity))
1247 (defun opaque-identity (x) x)
1248 (defstruct tricky-defaults
1249 (fun #'identity :type function)
1250 (num (opaque-identity 3) :type fixnum))
1251 (macrolet ((frob (form expected-expected-type)
1252 `(handler-case ,form
1253 (type-error (c) (assert (eq (type-error-expected-type c)
1254 ',expected-expected-type)))
1255 (:no-error (&rest vals) (error "~S returned values: ~S" ',form vals)))))
1256 (frob (make-tricky-defaults :fun 3) function)
1257 (frob (make-tricky-defaults :num #'identity) fixnum))
1259 (let ((fun (compile nil '(lambda (&key (key (opaque-identity 3)))
1260 (declare (optimize safety) (type integer key))
1262 (assert (= (funcall fun) 3))
1263 (assert (= (funcall fun :key 17) 17))
1264 (handler-case (funcall fun :key t)
1265 (type-error (c) (assert (eq (type-error-expected-type c) 'integer)))
1266 (:no-error (&rest vals) (error "no error"))))
1268 ;;; Basic compiler-macro expansion
1269 (define-compiler-macro test-cmacro-0 () ''expanded)
1271 (assert (eq 'expanded (funcall (lambda () (test-cmacro-0)))))
1273 ;;; FUNCALL forms in compiler macros, lambda-list parsing
1274 (define-compiler-macro test-cmacro-1
1275 (&whole whole a &optional b &rest c &key d)
1276 (list whole a b c d))
1278 (macrolet ((test (form a b c d)
1279 `(let ((form ',form))
1280 (destructuring-bind (whole a b c d)
1281 (funcall (compiler-macro-function 'test-cmacro-1) form nil)
1282 (assert (equal whole form))
1285 (assert (equal c ,c))
1286 (assert (eql d ,d))))) )
1287 (test (funcall 'test-cmacro-1 1 2 :d 3) 1 2 '(:d 3) 3)
1288 (test (test-cmacro-1 11 12 :d 13) 11 12 '(:d 13) 13))
1290 ;;; FUNCALL forms in compiler macros, expansions
1291 (define-compiler-macro test-cmacro-2 () ''ok)
1293 (assert (eq 'ok (funcall (lambda () (funcall 'test-cmacro-2)))))
1294 (assert (eq 'ok (funcall (lambda () (funcall #'test-cmacro-2)))))
1296 ;;; Shadowing of compiler-macros by local functions
1297 (define-compiler-macro test-cmacro-3 () ''global)
1299 (defmacro find-cmacro-3 (&environment env)
1300 (compiler-macro-function 'test-cmacro-3 env))
1302 (assert (funcall (lambda () (find-cmacro-3))))
1303 (assert (not (funcall (lambda () (flet ((test-cmacro-3 ()))
1304 (find-cmacro-3))))))
1305 (assert (eq 'local (funcall (lambda () (flet ((test-cmacro-3 () 'local))
1306 (test-cmacro-3))))))
1307 (assert (eq 'local (funcall (lambda () (flet ((test-cmacro-3 () 'local))
1308 (funcall #'test-cmacro-3))))))
1309 (assert (eq 'global (funcall (lambda () (flet ((test-cmacro-3 () 'local))
1310 (funcall 'test-cmacro-3))))))
1312 ;;; Local NOTINLINE & INLINE
1313 (defun test-cmacro-4 () 'fun)
1314 (define-compiler-macro test-cmacro-4 () ''macro)
1316 (assert (eq 'fun (funcall (lambda ()
1317 (declare (notinline test-cmacro-4))
1320 (assert (eq 'macro (funcall (lambda ()
1321 (declare (inline test-cmacro-4))
1324 ;;; SETF function compiler macros
1325 (define-compiler-macro (setf test-cmacro-4) (&whole form value) ''ok)
1327 (assert (eq 'ok (funcall (lambda () (setf (test-cmacro-4) 'zot)))))
1328 (assert (eq 'ok (funcall (lambda () (funcall #'(setf test-cmacro-4) 'zot)))))
1330 ;;; Step instrumentation breaking type-inference
1331 (handler-bind ((warning #'error))
1332 (assert (= 42 (funcall (compile nil '(lambda (v x)
1333 (declare (optimize sb-c:insert-step-conditions))
1334 (if (typep (the function x) 'fixnum)
1335 (svref v (the function x))
1337 nil (constantly 42)))))
1339 ;;; bug 368: array type intersections in the compiler
1343 (i368s (make-array 0 :fill-pointer t) :type (or (vector i368) null)))
1345 (g368 (error "missing :G368") :type g368 :read-only t))
1346 (declaim (ftype (function (fixnum (vector i368) e368) t) r368))
1347 (declaim (ftype (function (fixnum (vector e368)) t) h368))
1348 (defparameter *h368-was-called-p* nil)
1349 (defun nsu (vertices e368)
1350 (let ((i368s (g368-i368s (make-g368))))
1351 (let ((fuis (r368 0 i368s e368)))
1352 (format t "~&FUIS=~S~%" fuis)
1353 (or fuis (h368 0 i368s)))))
1355 (declare (ignore w x y))
1358 (declare (ignore w x))
1359 (setf *h368-was-called-p* t)
1360 (make-s368 :g368 (make-g368)))
1361 (let ((nsu (nsu #() (make-e368))))
1362 (format t "~&NSU returned ~S~%" nsu)
1363 (format t "~&*H368-WAS-CALLED-P*=~S~%" *h368-was-called-p*)
1364 (assert (s368-p nsu))
1365 (assert *h368-was-called-p*))
1367 ;;; bug 367: array type intersections in the compiler
1371 (i367s (make-array 0 :fill-pointer t) :type (or (vector i367) null)))
1373 (g367 (error "missing :G367") :type g367 :read-only t))
1374 (declaim (ftype (function ((vector i367) e367) (or s367 null)) r367))
1375 (declaim (ftype (function ((vector e367)) (values)) h367))
1376 (defun frob-367 (v w)
1377 (let ((x (g367-i367s (make-g367))))
1378 (let* ((y (or (r367 x w)
1381 (format t "~&Y=~S Z=~S~%" y z)
1383 (defun r367 (x y) (declare (ignore x y)) nil)
1384 (defun h367 (x) (declare (ignore x)) (values))
1385 (multiple-value-bind (res err) (ignore-errors (frob-367 0 (make-e367)))
1387 (assert (typep err 'type-error)))
1390 (delete-file (compile-file "circ-tree-test.lisp"))
1391 (storage-condition (e)
1394 ;;; warnings due to step-insturmentation
1395 (defclass debug-test-class () ())
1397 (compile nil '(lambda ()
1398 (declare (optimize (debug 3)))
1399 (defmethod print-object ((x debug-test-class) s)
1400 (call-next-method))))
1401 ((and (not style-warning) warning) (e)
1404 ;;; program-error from bad lambda-list keyword
1407 (funcall (lambda (&whole x)
1413 (let ((*evaluator-mode* :interpret))
1414 (funcall (eval '(lambda (&whole x)
1419 ;;; ignore &environment
1420 (handler-bind ((style-warning #'error))
1421 (compile nil '(lambda ()
1422 (defmacro macro-ignore-env (&environment env)
1423 (declare (ignore env))
1425 (compile nil '(lambda ()
1426 (defmacro macro-no-env ()
1429 (dolist (*evaluator-mode* '(:interpret :compile))
1430 (disassemble (eval '(defun disassemble-source-form-bug (x y z)
1431 (declare (optimize debug))