Another CHECKED-COMPILE in tests/compiler.impure.lisp
[sbcl.git] / tests / compiler.impure.lisp
blob4dade3b80bd4805a9e5f704a3ab9e26f02770f9f
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
8 ;;;; more information.
9 ;;;;
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
12 ;;;; from CMU CL.
13 ;;;;
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 (in-package :cl-user)
20 ;; The tests in this file do not work under the legacy interpreter.
21 ;; They mostly do work in the fast interpreter, and are either harmless
22 ;; or actually reasonable things to test.
23 (when (and (eq sb-ext:*evaluator-mode* :interpret)
24 (not (member :sb-fasteval *features*)))
25 (sb-ext:exit :code 104))
27 (load "compiler-test-util.lisp")
28 (use-package "TEST-UTIL")
29 (use-package "ASSERTOID")
31 ;;; Old CMU CL code assumed that the names of "keyword" arguments are
32 ;;; necessarily self-evaluating symbols, but ANSI Common Lisp allows
33 ;;; them to be any symbols, not necessarily keywords, and thus not
34 ;;; necessarily self-evaluating. Make sure that this works.
35 (defun newfangled-cons (&key ((left-thing x)) ((right-thing y)))
36 (cons x y))
37 (with-test (:name (:lambda-list &key :self-evaluating))
38 (assert (equal (cons 1 2) (newfangled-cons 'right-thing 2 'left-thing 1))))
40 ;;; ANSI specifically says that duplicate keys are OK in lambda lists,
41 ;;; with no special exception for macro lambda lists. (As reported by
42 ;;; Pierre Mai on cmucl-imp 2001-03-30, Python didn't think so. The
43 ;;; rest of the thread had some entertainment value, at least for me
44 ;;; (WHN). The unbelievers were besmote and now even CMU CL will
45 ;;; conform to the spec in this regard. Who needs diplomacy when you
46 ;;; have brimstone?:-)
47 (defmacro ayup-duplicate-keys-are-ok-i-see-the-lite (&key k)
49 (with-test (:name (:macro :lambda-list :duplicate &key :arguments))
50 (assert (equal (funcall (checked-compile
51 '(lambda ()
52 (ayup-duplicate-keys-are-ok-i-see-the-lite
53 :k 112))))
54 112))
55 (assert (equal (funcall (checked-compile
56 '(lambda ()
57 (ayup-duplicate-keys-are-ok-i-see-the-lite
58 :k 'x :k 'y))))
59 'x)))
61 ;;; As reported by Alexey Dejneka (sbcl-devel 2002-01-30), in
62 ;;; sbcl-0.7.1 plus his patch (i.e. essentially sbcl-0.7.1.2), the
63 ;;; compiler barfed on this, blowing up in FIND-IN-PHYSENV looking for
64 ;;; the LAMBDA-VAR named NUM. That was fixed in sbcl-0.7.1.3.
65 (defun parse-num (index)
66 (let (num x)
67 (flet ((digs ()
68 (setq num index))
69 (z ()
70 (let ()
71 (setq x nil))))
72 (when (and (digs) (digs)) x))))
74 ;;; Bug 132: The compiler used to fail to compile INTEGER-valued CATCH
75 ;;; tags. This was fixed by Alexey Dejneka in sbcl-0.7.1.14. (INTEGER
76 ;;; catch tags are still a bad idea because EQ is used to compare
77 ;;; tags, and EQ comparison on INTEGERs is unportable; but now it's a
78 ;;; compiler warning instead of a failure to compile.)
79 (with-test (:name (compile catch :integer-valued-tag :bug-132))
80 (multiple-value-bind (fun failure-p warnings style-warnings)
81 (checked-compile '(lambda () (catch 0 (print 1331 (make-broadcast-stream))))
82 :allow-style-warnings t)
83 (declare (ignore failure-p warnings))
84 (funcall fun)
85 (assert style-warnings)))
87 ;;; Bug 150: In sbcl-0.7.1.15, compiling this code caused a failure in
88 ;;; SB-C::ADD-TEST-CONSTRAINTS:
89 ;;; The value NIL is not of type SB-C::CONTINUATION.
90 ;;; This bug was fixed by APD in sbcl-0.7.1.30.
91 (defun bug150-test1 ()
92 (let* ()
93 (flet ((wufn () (glorp table1 4.9)))
94 (gleep *uustk* #'wufn "#1" (list)))
95 (if (eql (lo foomax 3.2))
96 (values)
97 (error "not ~S" '(eql (lo foomax 3.2))))
98 (values)))
99 ;;; A simpler test case for bug 150: The compiler died with the
100 ;;; same type error when trying to compile this.
101 (defun bug150-test2 ()
102 (let ()
103 (<)))
105 ;;; bug 147, fixed by APD 2002-04-28
107 ;;; This test case used to crash the compiler, e.g. with
108 ;;; failed AVER: "(= (LENGTH (BLOCK-SUCC CALL-BLOCK)) 1)"
109 (defun bug147 (string ind)
110 (flet ((digs ()
111 (let (old-index)
112 (if (and (< ind ind)
113 (typep (char string ind) '(member #\1)))
114 nil))))))
116 ;;; bug reported and fixed by Matthias Hoelzl sbcl-devel 2002-05-13
117 (defmacro foo-2002-05-13 () ''x)
118 (eval '(foo-2002-05-13))
119 (compile 'foo-2002-05-13)
120 (foo-2002-05-13) ; (The bug caused UNDEFINED-FUNCTION to be signalled here.)
122 ;;; floating point pain on the PPC.
124 ;;; This test case used to fail to compile on most powerpcs prior to
125 ;;; sbcl-0.7.4.2x, as floating point traps were being incorrectly
126 ;;; masked.
127 (defun floating-point-pain (x)
128 (declare (single-float x))
129 (log x))
131 ;;; bug found and fixed ca. sbcl-0.7.5.12: The INTERSECTION-TYPE
132 ;;; here satisfies "is a subtype of ARRAY-TYPE", but can't be
133 ;;; accessed with ARRAY-TYPE accessors like
134 ;;; ARRAY-TYPE-SPECIALIZED-ELEMENT-TYPE, so ARRAY-related
135 ;;; DEFTRANSFORMs died with TYPE-ERROR at compile time when
136 ;;; compiling the DEFUN here.
137 (defun stupid-input-to-smart-array-deftransforms-0-7-5-12 (v)
138 (declare (type (and simple-vector fwd-type-ref) v))
139 (aref v 0))
141 ;;; Ca. sbcl-0.7.5.15 the compiler would fail an internal consistency
142 ;;; check on this code because it expected all calls to %INSTANCE-REF
143 ;;; to be transformed away, but its expectations were dashed by perverse
144 ;;; code containing app programmer errors like this.
145 (defstruct something-known-to-be-a-struct x y)
146 (with-test (:name (compile defstruct :instance-ref))
147 (assert (nth-value
148 1 (checked-compile
149 ;; Python sees the structure accessor on the
150 ;; known-not-to-be-a-struct A5 value and is very, very
151 ;; disappointed in you. (But it doesn't signal BUG any
152 ;; more.)
153 `(lambda ()
154 (labels ((a1 (a2 a3)
155 (cond (t (a4 a2 a3))))
156 (a4 (a2 a3 a5 a6)
157 (declare (type (or simple-vector null) a5 a6))
158 (something-known-to-be-a-struct-x a5))
159 (a8 (a2 a3)
160 (a9 #'a1 a10 a2 a3))
161 (a11 (a2 a3)
162 (cond ((and (funcall a12 a2)
163 (funcall a12 a3))
164 (funcall a13 a2 a3))
166 (when a14
167 (let ((a15 (a1 a2 a3)))
169 a16))))
170 (values #'a17 #'a11)))
171 :allow-failure t :allow-warnings t :allow-style-warnings t))))
173 ;;; On the SPARC, there was an erroneous definition of some VOPs used
174 ;;; to compile LOGANDs, which would lead to compilation of the
175 ;;; following function giving rise to a compile-time error (bug
176 ;;; spotted and fixed by Raymond Toy for CMUCL)
177 (defun logand-sparc-bogons (a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10)
178 (declare (type (unsigned-byte 32) a0)
179 (type (signed-byte 32) a1 a2 a3 a4 a5 a6 a7 a8 a9 a10)
180 ;; to ensure that the call is a candidate for
181 ;; transformation
182 (optimize (speed 3) (safety 0) (compilation-speed 0) (debug 0)))
183 (values
184 ;; the call that fails compilation
185 (logand a0 a10)
186 ;; a call to prevent the other arguments from being optimized away
187 (logand a1 a2 a3 a4 a5 a6 a7 a8 a9)))
189 ;;; bug 192, reported by Einar Floystad Dorum sbcl-devel 2002-08-14,
190 ;;; fixed in sbcl-0.7.6.26: Compiling this function in 0.7.6 caused
191 ;;; the compiler to try to constant-fold DATA-VECTOR-REF, which is OK,
192 ;;; except that there was no non-VOP definition of DATA-VECTOR-REF, so
193 ;;; it would fail.
194 (defun bug192 ()
195 (funcall
196 (LAMBDA (TEXT I L )
197 (LABELS ((G908 (I)
198 (LET ((INDEX
200 (IF (= I L)
202 (LET ((S TEXT)
203 (E (ELT TEXT I)))
204 (DECLARE (IGNORABLE S E))
205 (WHEN (EQL #\a E)
206 (G909 (1+ I))))))))
207 INDEX))
208 (G909 (I)
210 (IF (= I L)
212 (LET ((S TEXT)
213 (E (ELT TEXT I)))
214 (DECLARE (IGNORABLE S E))
215 (WHEN (EQL #\b E) (G910 (1+ I)))))))
216 (G910 (I)
217 (LET ((INDEX
219 (IF NIL
221 (LET ((S TEXT))
222 (DECLARE (IGNORABLE S))
223 (WHEN T I))))))
224 INDEX)))
225 (G908 I))) "abcdefg" 0 (length "abcdefg")))
227 ;;; bugs #65, #70, and #109, closed by APD's patch sbcl-devel 2002-08-17
229 ;;; This was "YA code deletion bug" whose symptom was the failure of
230 ;;; the assertion
231 ;;; (EQ (C::LAMBDA-TAIL-SET C::CALLER)
232 ;;; (C::LAMBDA-TAIL-SET (C::LAMBDA-HOME C::CALLEE)))
233 ;;; at compile time.
234 (defun bug65-1 (termx termy) ; from Carl Witty on submit bugs list, debian.org
235 (labels
236 ((alpha-equal-bound-term-lists (listx listy)
237 (or (and (null listx) (null listy))
238 (and listx listy
239 (let ((bindings-x (bindings-of-bound-term (car listx)))
240 (bindings-y (bindings-of-bound-term (car listy))))
241 (if (and (null bindings-x) (null bindings-y))
242 (alpha-equal-terms (term-of-bound-term (car listx))
243 (term-of-bound-term (car listy)))
244 (and (= (length bindings-x) (length bindings-y))
245 (prog2
246 (enter-binding-pairs (bindings-of-bound-term (car listx))
247 (bindings-of-bound-term (car listy)))
248 (alpha-equal-terms (term-of-bound-term (car listx))
249 (term-of-bound-term (car listy)))
250 (exit-binding-pairs (bindings-of-bound-term (car listx))
251 (bindings-of-bound-term (car listy)))))))
252 (alpha-equal-bound-term-lists (cdr listx) (cdr listy)))))
254 (alpha-equal-terms (termx termy)
255 (if (and (variable-p termx)
256 (variable-p termy))
257 (equal-bindings (id-of-variable-term termx)
258 (id-of-variable-term termy))
259 (and (equal-operators-p (operator-of-term termx) (operator-of-term termy))
260 (alpha-equal-bound-term-lists (bound-terms-of-term termx)
261 (bound-terms-of-term termy))))))
263 (or (eq termx termy)
264 (and termx termy
265 (with-variable-invocation (alpha-equal-terms termx termy))))))
266 (defun bug65-2 () ; from Bob Rogers cmucl-imp 1999-07-28
267 ;; Given an FSSP alignment file named by the argument . . .
268 (labels ((get-fssp-char ()
269 (get-fssp-char))
270 (read-fssp-char ()
271 (get-fssp-char)))
272 ;; Stub body, enough to tickle the bug.
273 (list (read-fssp-char)
274 (read-fssp-char))))
275 (defun bug70 ; from David Young cmucl-help 30 Nov 2000
276 (item sequence &key (test #'eql))
277 (labels ((find-item (obj seq test &optional (val nil))
278 (let ((item (first seq)))
279 (cond ((null seq)
280 (values nil nil))
281 ((funcall test obj item)
282 (values val seq))
284 (find-item obj
285 (rest seq)
286 test
287 (nconc val `(,item))))))))
288 (find-item item sequence test)))
289 (defun bug109 () ; originally from CMU CL bugs collection, reported as
290 ; SBCL bug by MNA 2001-06-25
291 (labels
292 ((eff (&key trouble)
293 (eff)
294 ;; nil
295 ;; Uncomment and it works
297 (eff)))
299 ;;; bug 192a, fixed by APD "more strict type checking" patch
300 ;;; (sbcl-devel 2002-08-07)
301 (defun bug192a (x)
302 (declare (optimize (speed 0) (safety 3)))
303 ;; Even with bug 192a, this declaration was checked as an assertion.
304 (declare (real x))
305 (+ x
306 (locally
307 ;; Because of bug 192a, this declaration was trusted without checking.
308 (declare (single-float x))
309 (sin x))))
310 (with-test (:name (declare type :bug-192a))
311 (assert-error (bug192a nil) type-error)
312 (multiple-value-bind (result error) (ignore-errors (bug192a 100))
313 (assert (null result))
314 (assert (equal (type-error-expected-type error) 'single-float))))
316 ;;; bug 194, fixed in part by APD "more strict type checking" patch
317 ;;; (sbcl-devel 2002-08-07)
318 (with-test (:name (the :bug-194))
319 (assert-error (multiple-value-prog1 (progn (the real '(1 2 3)))) type-error)
320 (assert-error (the real '(1 2 3)) type-error))
322 (defun bug194d ()
323 (null (ignore-errors
324 (let ((arg1 1)
325 (arg2 (identity (the real #(1 2 3)))))
326 (if (< arg1 arg2) arg1 arg2)))))
327 (with-test (:name (the :bug-194d))
328 (assert (eq (bug194d) t)))
331 ;;; BUG 48a. and b. (symbol-macrolet handling), fixed by Eric Marsden
332 ;;; and Raymond Toy for CMUCL, fix ported for sbcl-0.7.6.18.
333 (flet ((test (form)
334 (multiple-value-bind (function failure-p)
335 (checked-compile form :allow-failure t)
336 (assert failure-p)
337 (assert-error (funcall function) program-error))))
339 (with-test (:name (compile symbol-macrolet :bug-48a))
340 (test `(lambda ()
341 ;; not interested in the package lock violation here
342 (declare (sb-ext:disable-package-locks t))
343 (symbol-macrolet ((t nil)) t))))
345 (with-test (:name (compile symbol-macrolet :bug-48b))
346 (test `(lambda ()
347 ;; not interested in the package lock violation here
348 (declare (sb-ext:disable-package-locks *standard-input*))
349 (symbol-macrolet ((*standard-input* nil))
350 *standard-input*))))
352 (with-test (:name (compile symbol-macrolet :bug-48c))
353 (test `(lambda ()
354 (symbol-macrolet ((s nil)) (declare (special s)) s)))))
357 ;;; bug 120a: Turned out to be constraining code looking like (if foo
358 ;;; <X> <X>) where <X> was optimized by the compiler to be the exact
359 ;;; same block in both cases, but not turned into (PROGN FOO <X>).
360 ;;; Fixed by APD in sbcl-0.7.7.2, who provided this test:
361 (declaim (inline dont-constrain-if-too-much))
362 (defun dont-constrain-if-too-much (frame up-frame)
363 (declare (optimize (speed 3) (safety 1) (debug 1)))
364 (if (or (not frame) t)
365 frame
366 "bar"))
367 (defun dont-constrain-if-too-much-aux (x y)
368 (declare (optimize (speed 3) (safety 1) (debug 1)))
369 (if x t (if y t (dont-constrain-if-too-much x y))))
371 (with-test (:name (if :constraint-propagation :bug-120a))
372 (assert (null (dont-constrain-if-too-much-aux nil nil))))
374 ;;; TYPE-ERROR confusion ca. sbcl-0.7.7.24, reported and fixed by
375 ;;; APD sbcl-devel 2002-09-14
376 (defun exercise-0-7-7-24-bug (x)
377 (declare (integer x))
378 (let (y)
379 (setf y (the single-float (if (> x 0) x 3f0)))
380 (list y y)))
381 (with-test (:name (type-error :0.7.7.24))
382 (assert-error (exercise-0-7-7-24-bug 4) type-error)
383 (assert (equal (exercise-0-7-7-24-bug -4) '(3f0 3f0))))
385 ;;; non-intersecting type declarations were DWIMing in a confusing
386 ;;; fashion until sbcl-0.7.7.28, when APD reported and fixed the
387 ;;; problem.
388 (defun non-intersecting-the (x)
389 (let (y)
390 (setf y (the single-float (the integer x)))
391 (list y y)))
393 (with-test (:name :non-intersecting-the)
394 (assert-error (non-intersecting-the 3) type-error)
395 (assert-error (non-intersecting-the 3f0) type-error))
397 ;;; until 0.8.2 SBCL did not check THEs in arguments
398 (defun the-in-arguments-aux (x)
400 (defun the-in-arguments-1 (x)
401 (list x (the-in-arguments-aux (the (single-float 0s0) x))))
402 (defun the-in-arguments-2 (x)
403 (list x (the-in-arguments-aux (the single-float x))))
405 (with-test (:name (the :argument))
406 (assert-error (the-in-arguments-1 1) type-error)
407 (assert-error (the-in-arguments-2 1) type-error))
409 ;;; bug 153: a hole in a structure slot type checking
410 (declaim (optimize safety))
411 (defstruct foo153
412 (bla 0 :type fixnum))
413 (defun bug153-1 ()
414 (let ((foo (make-foo153)))
415 (setf (foo153-bla foo) '(1 . 1))
416 (format t "Is ~a of type ~a a cons? => ~a~%"
417 (foo153-bla foo)
418 (type-of (foo153-bla foo))
419 (consp (foo153-bla foo)))))
420 (defun bug153-2 (x)
421 (let ((foo (make-foo153)))
422 (setf (foo153-bla foo) x)
423 (format t "Is ~a of type ~a a cons? => ~a~%"
424 (foo153-bla foo)
425 (type-of (foo153-bla foo))
426 (consp (foo153-bla foo)))))
428 (with-test (:name (:name defstruct :slot :type :bug-153))
429 (assert-error (bug153-1) type-error)
430 (assert-error (bug153-2 '(1 . 1)) type-error))
432 ;;;; bug 110: the compiler flushed the argument type test and the default
433 ;;;; case in the cond.
435 ;(locally (declare (optimize (safety 3) (speed 2)))
436 ; (defun bug110 (x)
437 ; (declare (optimize (safety 2) (speed 3)))
438 ; (declare (type (or string stream) x))
439 ; (cond ((typep x 'string) 'string)
440 ; ((typep x 'stream) 'stream)
441 ; (t
442 ; 'none))))
444 ;(multiple-value-bind (result condition)
445 ; (ignore-errors (bug110 0))
446 ; (declare (ignore result))
447 ; (assert (typep condition 'type-error)))
449 ;;; bug 202: the compiler failed to compile a function, which derived
450 ;;; type contradicted declared.
451 (declaim (ftype (function () null) bug202))
452 (defun bug202 ()
455 ;;; bugs 178, 199: compiler failed to compile a call of a function
456 ;;; with a hairy type
457 (defun bug178 (x)
458 (funcall (the function (the standard-object x))))
460 (defun bug199-aux (f)
461 (eq nil (funcall f)))
463 (defun bug199 (f x)
464 (declare (type (and function (satisfies bug199-aux)) f))
465 (funcall f x))
467 (with-test (:name (declaim &optional &rest :bogus style-warning))
468 (assert-no-signal
469 (ctu:file-compile
470 "(declaim (ftype (function (symbol &optional t &rest t)) foo))
471 (defun foo (x &optional y &rest z)
472 (declare (ignore x y z)))"
473 :load nil)
474 style-warning))
476 ;;; check non-toplevel DEFMACRO
477 (defvar *defmacro-test-status* nil)
479 (with-test (:name (compile-file defmacro))
480 (fmakunbound 'defmacro-test-aux)
481 (let* ((src "defmacro-test.lisp")
482 (obj (compile-file-pathname src)))
483 (unwind-protect
484 (progn
485 (compile-file src)
486 (assert (equal *defmacro-test-status* '(function a)))
487 (setq *defmacro-test-status* nil)
488 (load obj)
489 (assert (equal *defmacro-test-status* nil))
490 (macroexpand '(defmacro-test-aux 'a))
491 (assert (equal *defmacro-test-status* '(macro 'a z-value)))
492 (eval '(defmacro-test-aux 'a))
493 (assert (equal *defmacro-test-status* '(expanded 'a z-value))))
494 (ignore-errors (delete-file obj)))))
496 ;;; bug 204: EVAL-WHEN inside a local environment
497 (defvar *bug204-test-status*)
499 (with-test (:name (compile-file eval-when :local-environment :bug-204))
500 (let* ((src "bug204-test.lisp")
501 (obj (compile-file-pathname src)))
502 (unwind-protect
503 (progn
504 (setq *bug204-test-status* nil)
505 (compile-file src :verbose nil :print nil)
506 (assert (equal *bug204-test-status* '((:expanded :load-toplevel)
507 (:called :compile-toplevel)
508 (:expanded :compile-toplevel))))
509 (setq *bug204-test-status* nil)
510 (load obj)
511 (assert (equal *bug204-test-status* '((:called :load-toplevel)))))
512 (ignore-errors (delete-file obj)))))
514 ;;; toplevel SYMBOL-MACROLET
515 ;;; FIXME: I didn't look into why this fails in the interpreter, but it does.
516 (defvar *symbol-macrolet-test-status*)
518 (with-test (:name (compile-file symbol-macrolet) :skipped-on :interpreter)
519 (let* ((src "symbol-macrolet-test.lisp")
520 (obj (compile-file-pathname src)))
521 (unwind-protect
522 (progn
523 (setq *symbol-macrolet-test-status* nil)
524 (compile-file src :verbose nil :print nil)
525 (assert (equal *symbol-macrolet-test-status*
526 '(2 1)))
527 (setq *symbol-macrolet-test-status* nil)
528 (load obj)
529 (assert (equal *symbol-macrolet-test-status* '(2))))
530 (ignore-errors (delete-file obj)))))
532 ;;; On the x86, this code failed to compile until sbcl-0.7.8.37:
533 (defun x86-assembler-failure (x)
534 (declare (optimize (speed 3) (safety 0)))
535 (eq (setf (car x) 'a) nil))
537 ;;; bug 211: :ALLOW-OTHER-KEYS
538 (defun bug211d (&key (x :x x-p) ((:allow-other-keys y) :y y-p))
539 (list x x-p y y-p))
541 (with-test (:name (:allow-other-keys :bug-211d))
542 (assert (equal (bug211d) '(:x nil :y nil)))
543 (assert (equal (bug211d :x 1) '(1 t :y nil)))
544 (assert-error (bug211d :y 2) program-error)
545 (assert (equal (bug211d :y 2 :allow-other-keys t :allow-other-keys nil)
546 '(:x nil t t)))
547 (assert-error (bug211d :y 2 :allow-other-keys nil) program-error))
549 (checked-compile
550 '(lambda ()
551 (flet ((test (&key (x :x x-p) ((:allow-other-keys y) :y y-p))
552 (list x x-p y y-p)))
553 (assert (equal (test) '(:x nil :y nil)))
554 (assert (equal (test :x 1) '(1 t :y nil)))
555 (assert (equal (test :y 2 :allow-other-keys 11 :allow-other-keys nil)
556 '(:x nil 11 t)))))
557 :name 'bug211b)
558 (with-test (:name (compile :lambda-list :bug-211b))
559 (bug211b))
561 (with-test (:name (compile :lambda-list :bug-211c))
562 (let ((fun (checked-compile
563 '(lambda ()
564 (flet ((test (&key (x :x x-p))
565 (list x x-p)))
566 (assert (equal (test) '(:x nil)))
567 (assert (equal (test :x 1) '(1 t)))
568 (assert (equal (test :y 2 :allow-other-keys 11 :allow-other-keys nil)
569 '(:x nil))))))))
570 (funcall fun)))
572 (with-test (:name (compile :lambda-list :allow-other-keys
573 :bug-211 :do-not-allow))
574 (dolist (form '((test :y 2)
575 (test :y 2 :allow-other-keys nil)
576 (test :y 2 :allow-other-keys nil :allow-other-keys t)))
577 (multiple-value-bind (result failure-p)
578 (checked-compile
579 `(lambda ()
580 (flet ((test (&key (x :x x-p) ((:allow-other-keys y) :y y-p))
581 (list x x-p y y-p)))
582 ,form))
583 :allow-failure t :allow-warnings t)
584 (assert failure-p)
585 (assert-error (funcall result) program-error))))
587 ;;; bug 217: wrong type inference
588 (defun bug217-1 (x s)
589 (let ((f (etypecase x
590 (character #'write-char)
591 (integer #'write-byte))))
592 (funcall f x s)
593 (etypecase x
594 (character (write-char x s))
595 (integer (write-byte x s)))))
596 (with-test (:name (:bug-217))
597 (bug217-1 #\1 (make-broadcast-stream)))
599 ;;; bug 221: tried and died on CSUBTYPEP (not VALUES-SUBTYPEP) of the
600 ;;; function return types when inferring the type of the IF expression
601 (declaim (ftype (function (fixnum) (values package boolean)) bug221f1))
602 (declaim (ftype (function (t) (values package boolean)) bug221f2))
603 (defun bug221 (b x)
604 (funcall (if b #'bug221f1 #'bug221f2) x))
606 ;;; bug 172: macro lambda lists were too permissive until 0.7.9.28
607 ;;; (fix provided by Matthew Danish) on sbcl-devel
608 (with-test (:name (defmacro :lambda-list :bug-172))
609 (assert-error (defmacro bug172 (&rest rest foo) `(list ,rest ,foo))))
611 (with-test (:name (compile :embedded the))
612 (flet ((check-embedded-thes (policy1 policy2 x y)
613 (handler-case
614 (funcall (checked-compile
615 `(lambda (f)
616 (declare (optimize (speed 2) (safety ,policy1)))
617 (multiple-value-list
618 (the (values (integer 2 3) t &optional)
619 (locally (declare (optimize (safety ,policy2)))
620 (the (values t (single-float 2f0 3f0) &optional)
621 (funcall f)))))))
622 (lambda () (values x y)))
623 (type-error (error)
624 error))))
626 (assert (equal (check-embedded-thes 0 0 :a :b) '(:a :b)))
628 (assert (equal (check-embedded-thes 0 3 :a 2.5f0) '(:a 2.5f0)))
629 (assert (typep (check-embedded-thes 0 3 2 3.5f0) 'type-error))
631 (assert (equal (check-embedded-thes 0 1 :a 3.5f0) '(:a 3.5f0)))
632 (assert (typep (check-embedded-thes 0 1 2 2.5d0) 'type-error))
634 (assert (equal (check-embedded-thes 3 0 2 :a) '(2 :a)))
635 (assert (typep (check-embedded-thes 3 0 4 2.5f0) 'type-error))
637 (assert (equal (check-embedded-thes 1 0 3 :b) '(3 :b)))
638 (assert (typep (check-embedded-thes 1 0 1.0 2.5f0) 'type-error))
641 (assert (equal (check-embedded-thes 3 3 2 2.5f0) '(2 2.5f0)))
642 (assert (typep (check-embedded-thes 3 3 0 2.5f0) 'type-error))
643 (assert (typep (check-embedded-thes 3 3 2 3.5f0) 'type-error))))
646 ;;; INLINE inside MACROLET
647 (declaim (inline to-be-inlined))
648 (macrolet ((def (x) `(defun ,x (y) (+ y 1))))
649 (def to-be-inlined))
650 (defun call-inlined (z)
651 (to-be-inlined z))
652 (assert (= (call-inlined 3) 4))
653 (macrolet ((frob (x) `(+ ,x 3)))
654 (defun to-be-inlined (y)
655 (frob y)))
656 #-interpreter
657 (assert (= (call-inlined 3)
658 ;; we should have inlined the previous definition, so the
659 ;; new one won't show up yet.
661 (defun call-inlined (z)
662 (to-be-inlined z))
663 #-interpreter (assert (= (call-inlined 3) 6))
664 (defun to-be-inlined (y)
665 (+ y 5))
666 #-interpreter (assert (= (call-inlined 3) 6))
668 ;;; DEFINE-COMPILER-MACRO to work as expected, not via weird magical
669 ;;; IR1 pseudo-:COMPILE-TOPLEVEL handling
670 (defvar *bug219-a-expanded-p* nil)
671 (defun bug219-a (x)
672 (+ x 1))
673 (define-compiler-macro bug219-a (&whole form y)
674 (setf *bug219-a-expanded-p* t)
675 (if (constantp y)
676 (+ (eval y) 2)
677 form))
678 (defun bug219-a-aux ()
679 (bug219-a 2))
680 (defvar *bug219-a-temp* 3)
681 (with-test (:name (define-compiler-macro :bug-219a))
682 (assert (= (bug219-a-aux) (if *bug219-a-expanded-p* 4 3)))
683 (assert (= (bug219-a *bug219-a-temp*) 4)))
685 (defvar *bug219-b-expanded-p* nil)
686 (defun bug219-b-aux1 (x)
687 (when x
688 (define-compiler-macro bug219-b (y)
689 (setf *bug219-b-expanded-p* t)
690 `(+ ,y 2))))
691 (defun bug219-b-aux2 (z)
692 (bug219-b z))
693 (assert (not *bug219-b-expanded-p*))
694 (assert-error (bug219-b-aux2 1) undefined-function)
695 (bug219-b-aux1 t)
696 (defun bug219-b-aux2 (z)
697 (bug219-b z))
698 (defun bug219-b (x)
700 (assert (= (bug219-b-aux2 1)
701 (if *bug219-b-expanded-p* 3 1)))
703 ;;; bug 224: failure in unreachable code deletion
704 (defmacro do-optimizations (&body body)
705 `(dotimes (.speed. 4)
706 (dotimes (.space. 4)
707 (dotimes (.debug. 4)
708 (dotimes (.compilation-speed. 4)
709 (proclaim `(optimize (speed , .speed.) (space , .space.)
710 (debug , .debug.)
711 (compilation-speed , .compilation-speed.)))
712 ,@body)))))
714 (with-test (:name (:unreachable-code locally declare :bug-224))
715 (do-optimizations
716 (checked-compile
717 (read-from-string
718 "(lambda ()
719 (#:localy (declare (optimize (safety 3)))
720 (ignore-errors (progn (values-list (car (list '(1 . 2)))) t))))")
721 :allow-failure t :allow-style-warnings t)))
723 (with-test (:name (:unreachable-code error labels :bug-224))
724 (do-optimizations
725 (checked-compile
726 '(lambda ()
727 (labels ((ext ()
728 (tagbody
729 (labels ((i1 () (list (i2) (i2)))
730 (i2 () (list (int) (i1)))
731 (int () (go :exit)))
732 (list (i1) (i1) (i1)))
733 :exit (return-from ext))))
734 (list (error "nih") (ext) (ext)))))))
736 (with-test (:name (:unreachable-code error let :bug-224))
737 (do-optimizations
738 (checked-compile '(lambda (x) (let ((y (error ""))) (list x y))))))
740 ;;; bug 223: invalid moving of global function name referencing
741 (defun bug223-int (n)
742 `(int ,n))
744 (defun bug223-wrap ()
745 (let ((old #'bug223-int))
746 (setf (fdefinition 'bug223-int)
747 (lambda (n)
748 (assert (> n 0))
749 `(ext ,@(funcall old (1- n)))))))
751 (with-test (:name (compile setf fdefinition :bug-223))
752 (compile 'bug223-wrap)
753 (assert (equal (bug223-int 4) '(int 4)))
754 (bug223-wrap)
755 (assert (equal (bug223-int 4) '(ext int 3)))
756 (bug223-wrap)
757 (assert (equal (bug223-int 4) '(ext ext int 2))))
759 ;;; COERCE got its own DEFOPTIMIZER which has to reimplement most of
760 ;;; SPECIFIER-TYPE-NTH-ARG. For a while, an illegal type would throw
761 ;;; you into the debugger on compilation.
762 (defun coerce-defopt1 (x)
763 ;; illegal, but should be compilable.
764 (coerce x '(values t)))
765 (defun coerce-defopt2 (x)
766 ;; illegal, but should be compilable.
767 (coerce x '(values t &optional)))
768 (with-test (:name (coerce :optimizer))
769 (assert-error (coerce-defopt1 3))
770 (assert-error (coerce-defopt2 3)))
772 ;;; Oops. In part of the (CATCH ..) implementation of DEBUG-RETURN,
773 ;;; it was possible to confuse the type deriver of the compiler
774 ;;; sufficiently that compiler invariants were broken (explained by
775 ;;; APD sbcl-devel 2003-01-11).
777 ;;; WHN's original report
778 (defun debug-return-catch-break1 ()
779 (with-open-file (s "/tmp/foo"
780 :direction :output
781 :element-type (list
782 'signed-byte
784 (integer-length most-positive-fixnum))))
785 (read-byte s)
786 (read-byte s)
787 (read-byte s)
788 (read-byte s)))
790 ;;; APD's simplified test case
791 (defun debug-return-catch-break2 (x)
792 (declare (type (vector (unsigned-byte 8)) x))
793 (setq *y* (the (unsigned-byte 8) (aref x 4))))
795 ;;; FUNCTION-LAMBDA-EXPRESSION should return something that COMPILE
796 ;;; can understand. Here's a simple test for that on a function
797 ;;; that's likely to return a hairier list than just a lambda:
798 (macrolet ((def (fn) `(progn
799 (declaim (inline ,fn))
800 (defun ,fn (x) (1+ x)))))
801 (def bug228))
802 (with-test (:name (function-lambda-expression compile :bug-228))
803 (let ((x (function-lambda-expression #'bug228)))
804 (when x
805 (assert (= (funcall (checked-compile x) 1) 2)))))
808 (defun bug192b (i)
809 (dotimes (j i)
810 (declare (type (mod 4) i))
811 (unless (< i 5)
812 (print j))))
813 (with-test (:name :bug-192b)
814 (assert-error (bug192b 6) type-error))
816 (defun bug192c (x y)
817 (locally (declare (type fixnum x y))
818 (+ x (* 2 y))))
819 (with-test (:name :bug-192c)
820 (assert-error (bug192c 1.1 2) type-error)
821 (assert-error (progn (the real (list 1)) t) type-error))
823 (defun bug236 (a f)
824 (declare (optimize (speed 2) (safety 0)))
825 (+ 1d0
826 (the double-float
827 (multiple-value-prog1
828 (svref a 0)
829 (unless f (return-from bug236 0))))))
830 (with-test (:name :bug-236)
831 (assert (eql (bug236 #(4) nil) 0)))
833 ;;; Bug reported by reported by rif on c.l.l 2003-03-05
834 (defun test-type-of-special-1 (x)
835 (declare (special x)
836 (fixnum x)
837 (optimize (safety 3)))
838 (list x))
839 (defun test-type-of-special-2 (x)
840 (declare (special x)
841 (fixnum x)
842 (optimize (safety 3)))
843 (list x (setq x (/ x 2)) x))
844 (with-test (:name (declare special type))
845 (assert-error (test-type-of-special-1 3/2) type-error)
846 (assert-error (test-type-of-special-2 3) type-error)
847 (assert (equal (test-type-of-special-2 8) '(8 4 4))))
849 ;;; bug which existed in 0.8alpha.0.4 for several milliseconds before
850 ;;; APD fixed it in 0.8alpha.0.5
851 (defun frob8alpha04 (x y)
852 (+ x y))
853 (defun baz8alpha04 (this kids)
854 (flet ((n-i (&rest rest)
855 ;; Removing the #+NIL here makes the bug go away.
856 #+nil (format t "~&in N-I REST=~S~%" rest)
857 (apply #'frob8alpha04 this rest)))
858 (n-i kids)))
859 ;;; failed in 0.8alpha.0.4 with "The value 13 is not of type LIST."
860 (with-test (:name (&rest type-error))
861 (assert (= (baz8alpha04 12 13) 25)))
863 ;;; evaluation order in structure slot writers
864 (defstruct sswo
865 a b)
866 (with-test (:name (:evaluation-order structure :slot-writer))
867 (let* ((i 0)
868 (s (make-sswo :a (incf i) :b (incf i)))
869 (l (list s :v)))
870 (assert (= (sswo-a s) 1))
871 (assert (= (sswo-b s) 2))
872 (setf (sswo-a (pop l)) (pop l))
873 (assert (eq l nil))
874 (assert (eq (sswo-a s) :v))))
876 (defun bug249 (x)
877 (flet ((bar (y)
878 (declare (fixnum y))
879 (incf x)))
880 (list (bar x) (bar x) (bar x))))
882 (with-test (:name (flet declare type :bug-249))
883 (assert-error (bug249 1.0) type-error))
885 ;;; bug reported by ohler on #lisp 2003-07-10
886 (defun bug-ohler-2003-07-10 (a b)
887 (declare (optimize (speed 0) (safety 3) (space 0)
888 (debug 1) (compilation-speed 0)))
889 (adjoin a b))
891 ;;; bug reported by Doug McNaught on sbcl-devel 2003-09-14:
892 ;;; COMPILE-FILE did not bind *READTABLE*
893 (with-test (:name (compile-file *readtable*))
894 (let* ((source "bug-doug-mcnaught-20030914.lisp")
895 (fasl (compile-file-pathname source)))
896 (labels ((check ()
897 (assert (null (get-macro-character #\]))))
898 (full-check ()
899 (check)
900 (assert (typep *bug-doug-mcnaught-20030914*
901 '(simple-array (unsigned-byte 4) (*))))
902 (assert (equalp *bug-doug-mcnaught-20030914* #(1 2 3)))
903 (makunbound '*bug-doug-mcnaught-20030914*)))
904 (compile-file source)
905 (check)
906 (load fasl)
907 (full-check)
908 (load source)
909 (full-check)
910 (delete-file fasl))))
912 (defun expt-derive-type-bug (a b)
913 (unless (< a b)
914 (truncate (expt a b))))
915 (with-test (:name (expt :derive-type))
916 (assert (equal (multiple-value-list (expt-derive-type-bug 1 1))
917 '(1 0))))
919 ;;; Problems with type checking in functions with EXPLICIT-CHECK
920 ;;; attribute (reported by Peter Graves)
921 (with-test (:name (:type-checking :explicit-check))
922 (loop for (fun . args) in '((= a) (/= a)
923 (< a) (<= a) (> a) (>= a))
924 do (assert-error (apply fun args) type-error)))
926 (defclass broken-input-stream (sb-gray:fundamental-input-stream) ())
927 (defmethod sb-gray:stream-read-char ((stream broken-input-stream))
928 (throw 'break :broken))
929 (with-test (:name :explicit-check)
930 (assert (eql (block return
931 (handler-case
932 (catch 'break
933 (funcall (eval ''peek-char)
934 1 (make-instance 'broken-input-stream))
935 :test-broken)
936 (type-error (c)
938 (return-from return :good))))
939 :good)))
941 ;;;; MUFFLE-CONDITIONS test (corresponds to the test in the manual)
942 ; FIXME: make a better test!
943 (with-test (:name muffle-conditions :skipped-on '(or :alpha :x86-64))
944 (multiple-value-bind (fun failure-p warnings style-warnings notes)
945 (checked-compile
946 '(lambda (x)
947 (declare (optimize speed) (fixnum x))
948 (declare (sb-ext:muffle-conditions sb-ext:compiler-note))
949 (values (* x 5) ; no compiler note from this
950 (locally
951 (declare (sb-ext:unmuffle-conditions sb-ext:compiler-note))
952 ;; this one gives a compiler note
953 (* x -5)))))
954 (declare (ignore failure-p warnings))
955 (assert (= (length notes) 1))
956 (assert (equal (multiple-value-list (funcall fun 1)) '(5 -5)))))
958 (with-test (:name (flet labels &key))
959 (assert-error (eval '(flet ((%f (&key) nil)) (%f nil nil))))
960 (assert-error (eval '(labels ((%f (&key x) x)) (%f nil nil)))))
962 ;;; PROGV must not bind constants, or violate declared types -- ditto for SET.
963 (assert-error (set pi 3))
964 (assert-error (progv '(pi s) '(3 pi) (symbol-value x)))
965 (declaim (cons *special-cons*))
966 (assert-error (set '*special-cons* "nope") type-error)
967 (assert-error (progv '(*special-cons*) '("no hope") (car *special-cons*)) type-error)
969 ;;; No bogus warnings for calls to functions with complex lambda-lists.
970 (defun complex-function-signature (&optional x &rest y &key z1 z2)
971 (declare (ignore z1 z2))
972 (cons x y))
973 (with-test (:name :complex-call-doesnt-warn)
974 (checked-compile '(lambda (x) (complex-function-signature x :z1 1 :z2 2))))
976 (with-test (:name :non-required-args-update-info)
977 (let ((name (gensym "NON-REQUIRE-ARGS-TEST"))
978 (*evaluator-mode* :compile))
979 (eval `(defun ,name (x) x))
980 (assert (equal '(function (t) (values t &optional))
981 (sb-kernel:type-specifier (sb-int:proclaimed-ftype name))))
982 (eval `(defun ,name (x &optional y) (or x y)))
983 (assert (equal '(function (t &optional t) (values t &optional))
984 (sb-kernel:type-specifier (sb-int:proclaimed-ftype name))))))
986 ;;;; inline & maybe inline nested calls
988 (defun quux-marker (x) x)
989 (declaim (inline foo-inline))
990 (defun foo-inline (x) (quux-marker x))
991 (declaim (maybe-inline foo-maybe-inline))
992 (defun foo-maybe-inline (x) (quux-marker x))
994 (with-test (:name :nested-inline-calls)
995 (let ((fun (checked-compile `(lambda (x)
996 (foo-inline (foo-inline (foo-inline x)))))))
997 (assert (= 0 (ctu:count-full-calls "FOO-INLINE" fun)))
998 (assert (= 3 (ctu:count-full-calls "QUUX-MARKER" fun)))))
1000 (with-test (:name :nested-maybe-inline-calls)
1001 (let ((fun (checked-compile
1002 `(lambda (x)
1003 (declare (optimize (space 0)))
1004 (foo-maybe-inline (foo-maybe-inline (foo-maybe-inline x)))))))
1005 (assert (= 0 (ctu:count-full-calls "FOO-MAYBE-INLINE" fun)))
1006 (assert (= 1 (ctu:count-full-calls "QUUX-MARKER" fun)))))
1008 (with-test (:name :inline-calls)
1009 (let ((fun (checked-compile `(lambda (x)
1010 (list (foo-inline x)
1011 (foo-inline x)
1012 (foo-inline x))))))
1013 (assert (= 0 (ctu:count-full-calls "FOO-INLINE" fun)))
1014 (assert (= 3 (ctu:count-full-calls "QUUX-MARKER" fun)))))
1016 (with-test (:name :maybe-inline-calls)
1017 (let ((fun (checked-compile `(lambda (x)
1018 (declare (optimize (space 0)))
1019 (list (foo-maybe-inline x)
1020 (foo-maybe-inline x)
1021 (foo-maybe-inline x))))))
1022 (assert (= 0 (ctu:count-full-calls "FOO-MAYBE-INLINE" fun)))
1023 (assert (= 1 (ctu:count-full-calls "QUUX-MARKER" fun)))))
1025 (with-test (:name :bug-405)
1026 ;; These used to break with a TYPE-ERROR
1027 ;; The value NIL is not of type SB-C::PHYSENV.
1028 ;; in MERGE-LETS.
1029 (ctu:file-compile
1030 '((LET (outer-let-var)
1031 (lambda ()
1032 (print outer-let-var)
1033 (MULTIPLE-VALUE-CALL 'some-function
1034 (MULTIPLE-VALUE-CALL (LAMBDA (a) 'foo)
1035 1))))))
1036 (ctu:file-compile
1037 '((declaim (optimize (debug 3)))
1038 (defstruct bug-405-foo bar)
1039 (let ()
1040 (flet ((i (x) (frob x (bug-405-foo-bar foo))))
1041 (i :five))))))
1043 ;;; bug 235a
1044 (declaim (ftype (function (cons) number) bug-235a-aux))
1045 (declaim (inline bug-235a-aux))
1046 (defun bug-235a-aux (c)
1047 (the number (car c)))
1048 (with-test (:name :bug-235a)
1049 (let ((fun (checked-compile
1050 `(lambda (x y)
1051 (values (locally (declare (optimize (safety 0)))
1052 (bug-235a-aux x))
1053 (locally (declare (optimize (safety 3)))
1054 (bug-235a-aux y)))))))
1055 (assert
1056 (eq :error
1057 (handler-case
1058 (funcall fun '(:one) '(:two))
1059 (type-error (e)
1060 (assert (eq :two (type-error-datum e)))
1061 (assert (eq 'number (type-error-expected-type e)))
1062 :error))))))
1064 (with-test (:name :compiled-debug-funs-leak)
1065 (sb-ext:gc :full t)
1066 (let ((usage-before (sb-kernel::dynamic-usage)))
1067 (dotimes (x 10000)
1068 (let ((f (checked-compile '(lambda () (error "X")))))
1069 (handler-case
1070 (funcall f)
1071 (error () nil))))
1072 (sb-ext:gc :full t)
1073 (let ((usage-after (sb-kernel::dynamic-usage)))
1074 (when (< (+ usage-before 2000000) usage-after)
1075 (error "Leak")))))
1077 ;;; PROGV compilation and type checking when the declared type
1078 ;;; includes a FUNCTION subtype.
1079 (declaim (type (or (function (t) (values boolean &optional)) string)
1080 *hairy-progv-var*))
1081 (defvar *hairy-progv-var* #'null)
1082 (with-test (:name :hairy-progv-type-checking)
1083 (assert (eq :error
1084 (handler-case
1085 (progv '(*hairy-progv-var*) (list (eval 42))
1086 *hairy-progv-var*)
1087 (type-error () :error))))
1088 (assert (equal "GOOD!"
1089 (progv '(*hairy-progv-var*) (list (eval "GOOD!"))
1090 *hairy-progv-var*))))
1092 (with-test (:name :fill-complex-single-float)
1093 (assert (every (lambda (x) (eql x #c(-1.0 -2.0)))
1094 (funcall
1095 (lambda ()
1096 (make-array 2
1097 :element-type '(complex single-float)
1098 :initial-element #c(-1.0 -2.0)))))))
1100 (with-test (:name :make-array-symbol-as-initial-element)
1101 (assert (every (lambda (x) (eq x 'a))
1102 (funcall (checked-compile
1103 `(lambda ()
1104 (make-array 12 :initial-element 'a)))))))
1106 ;;; This non-minimal test-case catches a nasty error when loading
1107 ;;; inline constants.
1108 (deftype matrix ()
1109 `(simple-array single-float (16)))
1110 (declaim (ftype (sb-int:sfunction (single-float single-float single-float single-float
1111 single-float single-float single-float single-float
1112 single-float single-float single-float single-float
1113 single-float single-float single-float single-float)
1114 matrix)
1115 matrix)
1116 (inline matrix))
1117 (defun matrix (m11 m12 m13 m14
1118 m21 m22 m23 m24
1119 m31 m32 m33 m34
1120 m41 m42 m43 m44)
1121 (make-array 16
1122 :element-type 'single-float
1123 :initial-contents (list m11 m21 m31 m41
1124 m12 m22 m32 m42
1125 m13 m23 m33 m43
1126 m14 m24 m34 m44)))
1127 (declaim (ftype (sb-int:sfunction ((simple-array single-float (3)) single-float) matrix)
1128 rotate-around))
1129 (defun rotate-around (a radians)
1130 (let ((c (cos radians))
1131 (s (sin radians))
1132 ;; The 1.0 here was misloaded on x86-64.
1133 (g (- 1.0 (cos radians))))
1134 (let* ((x (aref a 0))
1135 (y (aref a 1))
1136 (z (aref a 2))
1137 (gxx (* g x x)) (gxy (* g x y)) (gxz (* g x z))
1138 (gyy (* g y y)) (gyz (* g y z)) (gzz (* g z z)))
1139 (matrix
1140 (+ gxx c) (- gxy (* s z)) (+ gxz (* s y)) 0.0
1141 (+ gxy (* s z)) (+ gyy c) (- gyz (* s x)) 0.0
1142 (- gxz (* s y)) (+ gyz (* s x)) (+ gzz c) 0.0
1143 0.0 0.0 0.0 1.0))))
1144 (with-test (:name :regression-1.0.29.54)
1145 (assert (every #'=
1146 '(-1.0 0.0 0.0 0.0 0.0 -1.0 0.0 0.0 0.0 0.0 -1.0 0.0 0.0 0.0 0.0 1.0)
1147 (rotate-around
1148 (make-array 3 :element-type 'single-float) (coerce pi 'single-float))))
1149 ;; Same bug manifests in COMPLEX-ATANH as well.
1150 (assert (= (atanh #C(-0.7d0 1.1d0)) #C(-0.28715567731069275d0 0.9394245539093365d0))))
1152 (with-test (:name :slot-value-on-structure)
1153 (let ((f (checked-compile `(lambda (x a b)
1154 (declare (something-known-to-be-a-struct x))
1155 (setf (slot-value x 'x) a
1156 (slot-value x 'y) b)
1157 (list (slot-value x 'x)
1158 (slot-value x 'y))))))
1159 (assert (equal '(#\x #\y)
1160 (funcall f
1161 (make-something-known-to-be-a-struct :x "X" :y "Y")
1162 #\x #\y)))
1163 (assert (not (ctu:find-named-callees f)))))
1165 (defclass some-slot-thing ()
1166 ((slot :initarg :slot)))
1167 (with-test (:name :with-slots-the)
1168 (let ((x (make-instance 'some-slot-thing :slot "foo")))
1169 (with-slots (slot) (the some-slot-thing x)
1170 (assert (equal "foo" slot)))))
1172 ;;; Missing &REST type in proclamation causing a miscompile.
1173 (declaim (ftype
1174 (function
1175 (sequence unsigned-byte
1176 &key (:initial-element t) (:initial-contents sequence))
1177 (values sequence &optional))
1178 bug-458354))
1179 (defun bug-458354
1180 (sequence length
1181 &rest keys
1182 &key (initial-element nil iep) (initial-contents nil icp))
1183 (declare (sb-ext:unmuffle-conditions style-warning))
1184 (declare (ignorable keys initial-element iep initial-contents icp))
1185 (apply #'sb-sequence:make-sequence-like sequence length keys))
1186 (with-test (:name :bug-458354)
1187 (assert (equalp #((a b) (a b)) (bug-458354 #(1 2) 2 :initial-element '(a b)))))
1189 (with-test (:name :bug-542807)
1190 (handler-bind ((style-warning #'error))
1191 (eval '(defstruct bug-542807 slot)))
1192 (let (conds)
1193 (handler-bind ((style-warning (lambda (c)
1194 (push c conds))))
1195 (eval '(defstruct bug-542807 slot)))
1196 (assert (and conds
1197 (every (lambda (x) (typep x 'sb-kernel:redefinition-with-defun))
1198 conds)))))
1200 (with-test (:name :defmacro-not-list-lambda-list)
1201 (assert-error (eval `(defmacro ,(gensym) "foo"))
1202 type-error))
1204 (with-test (:name :bug-308951)
1205 (let ((x 1))
1206 (dotimes (y 10)
1207 (let ((y y))
1208 (when (funcall (eval #'(lambda (x) (eql x 2))) y)
1209 (defun bug-308951-foo (z)
1210 (incf x (incf y z))))))
1211 (defun bug-308951-bar (z)
1212 (bug-308951-foo z)
1213 (values x)))
1214 (assert (= 4 (bug-308951-bar 1))))
1216 (declaim (inline bug-308914-storage))
1217 (defun bug-308914-storage (x)
1218 (the (simple-array flt (*)) (bug-308914-unknown x)))
1220 (with-test (:name :bug-308914-workaround)
1221 ;; This used to hang in ORDER-UVL-SETS.
1222 (handler-case
1223 (with-timeout 10
1224 (checked-compile
1225 `(lambda (lumps &key cg)
1226 (let ((nodes (map 'list (lambda (lump)
1227 (bug-308914-storage lump))
1228 lumps)))
1229 (setf (aref nodes 0) 2)
1230 (assert (every #'~= (apply #'concatenate 'list nodes) '(2 3 6 9)))))
1231 :allow-warnings t :allow-style-warnings t))
1232 (sb-ext:timeout ()
1233 (error "Hang in ORDER-UVL-SETS?"))))
1235 (declaim (inline inlined-function-in-source-path))
1236 (defun inlined-function-in-source-path (x)
1237 (+ x x))
1239 (with-test (:name :inlined-function-in-source-path)
1240 (let ((output
1241 (with-output-to-string (*error-output*)
1242 (compile nil `(lambda (x)
1243 (declare (optimize speed))
1244 (funcall #'inlined-function-in-source-path x))))))
1245 ;; We want the name
1246 (assert (search "INLINED-FUNCTION-IN-SOURCE-PATH" output))
1247 ;; ...not the leaf.
1248 (assert (not (search "DEFINED-FUN" output)))))
1250 (defmacro bug-795705 ()
1253 (with-test (:name :bug-795705)
1254 (assert (macro-function 'bug-795705))
1255 (fmakunbound 'bug-795705)
1256 (assert (not (macro-function 'bug-795705))))
1258 (with-test (:name (load-time-value :type-derivation))
1259 (let ((name 'load-time-value-type-derivation-test))
1260 (labels ((funtype (fun)
1261 (sb-kernel:type-specifier
1262 (sb-kernel:single-value-type
1263 (sb-kernel:fun-type-returns
1264 (sb-kernel:specifier-type
1265 (sb-kernel:%simple-fun-type fun))))))
1266 (test (type1 type2 form value-cell-p)
1267 (declare (ignore value-cell-p))
1268 (let* ((lambda-form `(lambda ()
1269 (load-time-value ,form)))
1270 (core-fun (checked-compile lambda-form))
1271 (core-type (funtype core-fun))
1272 (defun-form `(defun ,name ()
1273 (load-time-value ,form)))
1274 (file-fun (let ((*error-output* (make-broadcast-stream)))
1275 (ctu:file-compile (list defun-form) :load t)
1276 (symbol-function name)))
1277 (file-type (funtype file-fun)))
1278 (unless (subtypep core-type type1)
1279 (error "core: wanted ~S, got ~S" type1 core-type))
1280 (unless (subtypep file-type type2)
1281 (error "file: wanted ~S, got ~S" type2 file-type)))))
1282 (let ((* 10))
1283 (test '(integer 11 11) 'number
1284 '(+ * 1) nil))
1285 (let ((* "fooo"))
1286 (test '(integer 4 4) 'unsigned-byte
1287 '(length *) nil))
1288 (test '(integer 10 10) '(integer 10 10) 10 nil)
1289 (test 'cons 'cons '(cons t t) t))))
1291 (with-test (:name (load-time-value :errors))
1292 (multiple-value-bind (warn fail)
1293 (ctu:file-compile
1294 `((defvar *load-time-value-error-value* 10)
1295 (declaim (fixnum *load-time-value-error-value*))
1296 (defun load-time-value-error-test-1 ()
1297 (the list (load-time-value *load-time-value-error-value*))))
1298 :load t)
1299 (assert warn)
1300 (assert fail))
1301 (handler-case (load-time-value-error-test-1)
1302 (type-error (e)
1303 (and (eql 10 (type-error-datum e))
1304 (eql 'list (type-error-expected-type e)))))
1305 (multiple-value-bind (warn2 fail2)
1306 (ctu:file-compile
1307 `((defun load-time-value-error-test-2 ()
1308 (the list (load-time-value 10))))
1309 :load t)
1310 (assert warn2)
1311 (assert fail2))
1312 (handler-case (load-time-value-error-test-2)
1313 (type-error (e)
1314 (and (eql 10 (type-error-datum e))
1315 (eql 'list (type-error-expected-type e))))))
1317 ;;;; tests for compiler output
1318 (with-test (:name :unexpected-compiler-output)
1319 (let* ((*error-output* (make-string-output-stream))
1320 (output (with-output-to-string (*standard-output*)
1321 (compile-file "compiler-output-test.lisp"
1322 :print nil :verbose nil))))
1323 (unless (zerop (length output))
1324 (error "Unexpected output: ~S" output))))
1326 (with-test (:name :bug-493380)
1327 (flet ((test (forms)
1328 (catch 'debug
1329 (let ((*debugger-hook* (lambda (condition if)
1330 (declare (ignore if))
1331 (throw 'debug
1332 (if (typep condition 'serious-condition)
1333 :debug
1334 :oops)))))
1335 (multiple-value-bind (warned failed) (ctu:file-compile forms)
1336 (when (and warned failed)
1337 :failed))))))
1338 (assert (eq :failed (test "(defun")))
1339 (assert (eq :failed (test "(defun no-pkg::foo ())")))
1340 (assert (eq :failed (test "(cl:no-such-sym)")))
1341 (assert (eq :failed (test "...")))))
1343 (defun cmacro-signals-error () :fun)
1344 (define-compiler-macro cmacro-signals-error () (error "oops"))
1346 (with-test (:name :cmacro-signals-error)
1347 (multiple-value-bind (fun failure-p warnings)
1348 (checked-compile `(lambda () (cmacro-signals-error))
1349 :allow-failure t :allow-warnings t)
1350 (assert (and fun failure-p warnings))
1351 (assert (eq :fun (funcall fun)))))
1353 (defun cmacro-with-simple-key (&key a)
1354 (format nil "fun=~A" a))
1355 (define-compiler-macro cmacro-with-simple-key (&whole form &key a)
1356 (if (constantp a)
1357 (format nil "cmacro=~A" (eval a))
1358 form))
1360 (with-test (:name (:cmacro-with-simple-key :no-key))
1361 (let ((fun (checked-compile `(lambda () (cmacro-with-simple-key)))))
1362 (assert (string= "cmacro=NIL" (funcall fun)))))
1364 (with-test (:name (:cmacro-with-simple-key :constant-key))
1365 (let ((fun (checked-compile `(lambda () (cmacro-with-simple-key :a 42)))))
1366 (assert (string= "cmacro=42" (funcall fun)))))
1368 (with-test (:name (:cmacro-with-simple-key :variable-key))
1369 (let ((fun (checked-compile `(lambda (x) (cmacro-with-simple-key x 42)))))
1370 (assert (string= "fun=42" (funcall fun :a)))))
1372 (defun cmacro-with-nasty-key (&key ((nasty-key var)))
1373 (format nil "fun=~A" var))
1374 (define-compiler-macro cmacro-with-nasty-key (&whole form &key ((nasty-key var)))
1375 (if (constantp var)
1376 (format nil "cmacro=~A" (eval var))
1377 form))
1379 (with-test (:name (:cmacro-with-nasty-key :no-key))
1380 (let ((fun (checked-compile `(lambda () (cmacro-with-nasty-key)))))
1381 (assert (string= "cmacro=NIL" (funcall fun)))))
1383 (with-test (:name (:cmacro-with-nasty-key :constant-key))
1384 ;; This bogosity is thanks to cmacro lambda lists being /macro/ lambda
1385 ;; lists.
1386 (let ((fun (checked-compile
1387 `(lambda () (cmacro-with-nasty-key 'nasty-key 42)))))
1388 (assert (string= "fun=42" (funcall fun)))))
1390 (with-test (:name (:cmacro-with-nasty-key :variable-key))
1391 (let ((fun (checked-compile
1392 `(lambda (nasty-key) (cmacro-with-nasty-key nasty-key 42)))))
1393 (assert (string= "fun=42" (funcall fun 'nasty-key)))))
1395 (defconstant tricky-key 'tricky-key)
1396 (defun cmacro-with-tricky-key (&key ((tricky-key var)))
1397 (format nil "fun=~A" var))
1398 (define-compiler-macro cmacro-with-tricky-key (&whole form &key ((tricky-key var)))
1399 (if (constantp var)
1400 (format nil "cmacro=~A" (eval var))
1401 form))
1403 (with-test (:name (:cmacro-with-tricky-key :no-key))
1404 (let ((fun (checked-compile
1405 `(lambda () (cmacro-with-tricky-key)))))
1406 (assert (string= "cmacro=NIL" (funcall fun)))))
1408 (with-test (:name (:cmacro-with-tricky-key :constant-quoted-key))
1409 ;; This bogosity is thanks to cmacro lambda lists being /macro/ lambda
1410 ;; lists.
1411 (let ((fun (checked-compile
1412 `(lambda () (cmacro-with-tricky-key 'tricky-key 42)))))
1413 (assert (string= "fun=42" (funcall fun)))))
1415 (with-test (:name (:cmacro-with-tricky-key :constant-unquoted-key))
1416 (let ((fun (checked-compile
1417 `(lambda () (cmacro-with-tricky-key tricky-key 42)))))
1418 (assert (string= "cmacro=42" (funcall fun)))))
1420 (with-test (:name (:cmacro-with-tricky-key :variable-key))
1421 (let ((fun (checked-compile
1422 `(lambda (x) (cmacro-with-tricky-key x 42)))))
1423 (assert (string= "fun=42" (funcall fun 'tricky-key)))))
1425 (defun test-function-983 (x) x)
1426 (define-compiler-macro test-function-983 (x) x)
1428 (with-test (:name :funcall-compiler-macro)
1429 (assert
1430 (handler-case
1431 (and (compile nil
1432 `(lambda ()
1433 (funcall (function test-function-983 junk) 1)))
1434 nil)
1435 (sb-c:compiler-error () t))))
1437 (defsetf test-984 %test-984)
1439 (with-test (:name :setf-function-with-setf-expander)
1440 (assert
1441 (handler-case
1442 (and (defun (setf test-984) ())
1443 nil)
1444 (style-warning () t)))
1445 (checked-compile `(lambda () #'(setf test-984))
1446 :allow-style-warnings t))
1448 (with-test (:name :compile-setf-function)
1449 (defun (setf compile-setf) ())
1450 (assert (equal (compile '(setf compile-setf))
1451 '(setf compile-setf))))
1453 (declaim (inline cut-test))
1454 (defun cut-test (b)
1455 (cond ((integerp b) b)
1456 (b 469)
1457 (t 2)))
1459 (with-test (:name :cut-to-width-bad-constant)
1460 (assert (= (funcall (checked-compile
1461 `(lambda ()
1462 (multiple-value-bind (a b) (values t t)
1463 (declare (ignore b))
1464 (mask-field (byte 10 0) (cut-test a))))))
1465 469)))
1467 ;; META: there's a test in compiler.pure.lisp that also tests
1468 ;; interaction of PROGV with (debug 3). These tests should be together.
1469 (with-test (:name :progv-debug-3)
1470 (unwind-protect
1471 (sb-ext:restrict-compiler-policy 'debug 3)
1472 (assert (funcall (checked-compile
1473 `(lambda (*v*)
1474 (declare (special *v*))
1475 (progv '(*v*) '())
1476 (boundp '*v*)))
1478 (sb-ext:restrict-compiler-policy 'debug 0)))
1480 (with-test (:name :restrict-compiler-policy-result)
1481 (let ((sb-c::*policy-min* sb-c::*policy-min*)
1482 (sb-c::*policy-max* sb-c::*policy-max*))
1483 (sb-ext:restrict-compiler-policy 'safety 2)
1484 (checked-compile '(lambda () (declare (optimize (safety 0))))))
1485 (let ((sb-c::*policy-min* sb-c::*policy-min*)
1486 (sb-c::*policy-max* sb-c::*policy-max*))
1487 ;; Passing no arguments returns the current quality/value pairs.
1488 (assert (null (sb-ext:restrict-compiler-policy)))
1489 (let ((res (sb-ext:restrict-compiler-policy 'safety 2)))
1490 ;; returns an alist
1491 (assert (equal res '((safety . 2)))))
1492 (let ((res (sb-ext:restrict-compiler-policy 'debug 3)))
1493 ;; returns an alist, indeterminate order
1494 (assert (or (equal res '((safety . 2) (debug . 3)))
1495 (equal res '((debug . 3) (safety . 2))))))
1496 ;; remove the SAFETY restriction
1497 (let ((res (sb-ext:restrict-compiler-policy 'safety 0)))
1498 (assert (equal res '((debug . 3)))))
1499 ;; remove the DEBUG restriction
1500 (let ((res (sb-ext:restrict-compiler-policy 'debug 0)))
1501 (assert (null res)))))
1503 ;;;; tests not in the problem domain, but of the consistency of the
1504 ;;;; compiler machinery itself
1506 (in-package "SB-C")
1508 ;;; Hunt for wrong-looking things in fundamental compiler definitions,
1509 ;;; and gripe about them.
1511 ;;; FIXME: It should be possible to (1) repair the things that this
1512 ;;; code gripes about, and then (2) make the code signal errors
1513 ;;; instead of just printing complaints to standard output, in order
1514 ;;; to prevent the code from later falling back into disrepair.
1515 (defun grovel-results (function)
1516 (dolist (template (fun-info-templates (info :function :info function)))
1517 (when (template-more-results-type template)
1518 (format t "~&Template ~A has :MORE results, and translates ~A.~%"
1519 (template-name template)
1520 function)
1521 (return nil))
1522 (when (eq (template-result-types template) :conditional)
1523 ;; dunno.
1524 (return t))
1525 (let ((types (template-result-types template))
1526 (result-type (fun-type-returns (proclaimed-ftype function))))
1527 (cond
1528 ((values-type-p result-type)
1529 (do ((ltypes (append (args-type-required result-type)
1530 (args-type-optional result-type))
1531 (rest ltypes))
1532 (types types (rest types)))
1533 ((null ltypes)
1534 (unless (null types)
1535 #+nil
1536 (format t "~&More types than ltypes in ~A, translating ~A.~%"
1537 (template-name template)
1538 function)
1539 (return nil)))
1540 (when (null types)
1541 (unless (null ltypes)
1542 #+nil
1543 (format t "~&More ltypes than types in ~A, translating ~A.~%"
1544 (template-name template)
1545 function)
1546 (return nil)))))
1547 ((eq result-type (specifier-type nil))
1548 (unless (null types)
1549 (format t "~&Template ~A returns values for function ~A with RESULT-TYPE NIL.~%"
1550 (template-name template)
1551 function)
1552 (return nil)))
1553 ((/= (length types) 1)
1554 (format t "~&Template ~A isn't returning 1 value for ~A.~%"
1555 (template-name template)
1556 function)
1557 (return nil))
1558 (t t)))))
1559 (test-util:with-test (:name :identify-suspect-vops)
1560 (sb-int:call-with-each-globaldb-name
1561 (lambda (name)
1562 ;; LEGAL-FUN-NAME-P test is necessary, since (INFO :FUNCTION :TYPE)
1563 ;; has a defaulting expression that involves calling FDEFINITION.
1564 (when (and (legal-fun-name-p name) (proclaimed-ftype name))
1565 ;; OK, so we have an entry in the INFO database. Now, if ...
1566 (binding* ((info (info :function :info name) :exit-if-null)
1567 (nil (fun-info-templates info) :exit-if-null))
1568 ;; ... it has translators
1569 (grovel-results name))))))
1571 ;;;; bug 305: INLINE/NOTINLINE causing local ftype to be lost
1573 (test-util:with-test (:name (compile inline notinline))
1574 (labels ((compile-lambda (type sense allow-notes)
1575 (nth-value
1576 4 (test-util:checked-compile
1577 `(lambda ()
1578 (declare
1579 ,@(when type '((ftype (function () (integer 0 10)) bug-305)))
1580 (,sense bug-305)
1581 (optimize speed))
1582 (1+ (bug-305)))
1583 :allow-style-warnings t :allow-notes allow-notes))))
1584 (assert (compile-lambda nil 'inline t))
1585 (assert (compile-lambda nil 'notinline t))
1586 (compile-lambda t 'inline nil)
1587 (compile-lambda t 'notinline nil)))
1589 ;;; bug 211e: bogus style warning from duplicated keyword argument to
1590 ;;; a local function.
1591 (test-util:with-test (:name (compile flet :duplicate &key :bug-211e))
1592 (let ((f (test-util:checked-compile
1593 '(lambda ()
1594 (flet ((foo (&key y) (list y)))
1595 (list (foo :y 1 :y 2)))))))
1596 (assert (equal '((1)) (funcall f)))))
1598 ;;; check that EQL is optimized when other argument is (OR SYMBOL FIXNUM).
1599 (test-util:with-test (:name (compile :optimize eql))
1600 (let ((f1 (test-util:checked-compile
1601 '(lambda (x1 y1)
1602 (declare (type (or symbol fixnum) x1)
1603 (optimize speed))
1604 (eql x1 y1))
1605 :allow-notes nil))
1606 (f2 (test-util:checked-compile
1607 '(lambda (x2 y2)
1608 (declare (type (or symbol fixnum) y2)
1609 (optimize speed))
1610 (eql x2 y2))
1611 :allow-notes nil)))
1612 (let ((fix (random most-positive-fixnum))
1613 (sym (gensym))
1614 (e-count 0))
1615 (assert (funcall f1 fix fix))
1616 (assert (funcall f2 fix fix))
1617 (assert (funcall f1 sym sym))
1618 (assert (funcall f2 sym sym))
1619 (handler-bind ((type-error (lambda (c)
1620 (incf e-count)
1621 (continue c))))
1622 (flet ((test (f x y)
1623 (with-simple-restart (continue "continue with next test")
1624 (funcall f x y)
1625 (error "fell through with (~S ~S ~S)" f x y))))
1626 (test f1 "oops" 42)
1627 (test f1 (1+ most-positive-fixnum) 42)
1628 (test f2 42 "oops")
1629 (test f2 42 (1+ most-positive-fixnum))))
1630 (assert (= e-count 4)))))
1632 ;;; bug #389 (Rick Taube sbcl-devel)
1633 (declaim (ftype function bes-j0 bes-j1))
1634 (defun bes-jn (unn ux)
1635 (let ((nn unn) (x ux))
1636 (let* ((n (floor (abs nn)))
1637 (besn
1638 (if (= n 0)
1639 (bes-j0 x)
1640 (if (= n 1)
1641 (bes-j1 x)
1642 (if (zerop x)
1644 (let ((iacc 40)
1645 (ans 0.0)
1646 (bigno 1.0e+10)
1647 (bigni 1.0e-10))
1648 (if (> (abs x) n)
1649 (do ((tox (/ 2.0 (abs x)))
1650 (bjm (bes-j0 (abs x)))
1651 (bj (bes-j1 (abs x)))
1652 (j 1 (+ j 1))
1653 (bjp 0.0))
1654 ((= j n) (setf ans bj))
1655 (setf bjp (- (* j tox bj) bjm))
1656 (setf bjm bj)
1657 (setf bj bjp))
1658 (let ((tox (/ 2.0 (abs x)))
1660 (* 2
1661 (floor
1662 (/ (+ n (sqrt (* iacc n)))
1663 2))))
1664 (jsum 0.0)
1665 (bjm 0.0)
1666 (sum 0.0)
1667 (bjp 0.0)
1668 (bj 1.0))
1669 (do ((j m (- j 1)))
1670 ((= j 0))
1671 (setf bjm (- (* j tox bj) bjp))
1672 (setf bjp bj)
1673 (setf bj bjm)
1674 (when (> (abs bj) bigno)
1675 (setf bj (* bj bigni))
1676 (setf bjp (* bjp bigni))
1677 (setf ans (* ans bigni))
1678 (setf sum (* sum bigni)))
1679 (if (not (= 0 jsum)) (incf sum bj))
1680 (setf jsum (- 1 jsum))
1681 (if (= j n) (setf ans bjp)))
1682 (setf sum (- (* 2.0 sum) bj))
1683 (setf ans (/ ans sum))))
1684 (if (and (minusp x) (oddp n))
1685 (- ans)
1686 ans)))))))
1687 (if (and (minusp nn) (oddp nn)) (- besn) besn))))
1690 ;;; bug 233b: lvar lambda-var equality in constraint propagation
1692 ;; Put this in a separate function.
1693 (defun test-constraint-propagation/ref ()
1694 (let ((x nil))
1695 (if (multiple-value-prog1 x (setq x t))
1697 x)))
1699 (test-util:with-test (:name (:compiler :constraint-propagation :ref))
1700 (assert (eq t (test-constraint-propagation/ref))))
1702 ;; Put this in a separate function.
1703 (defun test-constraint-propagation/typep (x y)
1704 (if (typep (multiple-value-prog1 x (setq x y))
1705 'double-float)
1706 (+ x 1d0)
1707 (+ x 2)))
1709 (test-util:with-test (:name (:compiler :constraint-propagation :typep))
1710 (assert (= 6.0d0 (test-constraint-propagation/typep 1d0 5))))
1712 (test-util:with-test (:name (:compiler :constraint-propagation :eq/eql))
1713 (assert (eq :right (let ((c :wrong))
1714 (if (eq (let ((x c))
1715 (setq c :right)
1717 :wrong)
1719 0)))))
1721 ;;; Put this in a separate function.
1722 (defun test-constraint-propagation/cast (x)
1723 (when (the double-float (multiple-value-prog1
1725 (setq x (1+ x))))
1728 (test-util:with-test (:name (:compiler :constraint-propagation :cast))
1729 (assertoid:assert-error
1730 (test-constraint-propagation/cast 1) type-error))
1732 ;;; bug #399
1733 (let ((result (make-array 50000 :fill-pointer 0 :adjustable t)))
1734 (defun string->html (string &optional (max-length nil))
1735 (when (and (numberp max-length)
1736 (> max-length (array-dimension result 0)))
1737 (setf result (make-array max-length :fill-pointer 0 :adjustable t)))
1738 (let ((index 0)
1739 (left-quote? t))
1740 (labels ((add-char (it)
1741 (setf (aref result index) it)
1742 (incf index))
1743 (add-string (it)
1744 (loop for ch across it do
1745 (add-char ch))))
1746 (loop for char across string do
1747 (cond ((char= char #\<)
1748 (add-string "&lt;"))
1749 ((char= char #\>)
1750 (add-string "&gt;"))
1751 ((char= char #\&)
1752 (add-string "&amp;"))
1753 ((char= char #\')
1754 (add-string "&#39;"))
1755 ((char= char #\newline)
1756 (add-string "<br>"))
1757 ((char= char #\")
1758 (if left-quote? (add-string "&#147;") (add-string "&#148;"))
1759 (setf left-quote? (not left-quote?)))
1761 (add-char char))))
1762 (setf (fill-pointer result) index)
1763 (coerce result 'string)))))
1765 ;;; Calling thru constant symbols
1766 (require :sb-introspect)
1768 (declaim (inline target-fun))
1769 (defun target-fun (arg0 arg1)
1770 (+ arg0 arg1))
1771 (declaim (notinline target-fun))
1773 ;; FIXME: should use compiler-test-util, not sb-introspect here.
1774 ;; That issue aside, neither sb-introspect nor ctu:find-named-callees
1775 ;; can examine an interpreted function for its callees,
1776 ;; so we can't actually use this function.
1777 (defun test-target-fun-called (fun res)
1778 (assert (member #'target-fun
1779 (sb-introspect:find-function-callees #'caller-fun-1)))
1780 (assert (equal (funcall fun) res)))
1782 (defun caller-fun-1 ()
1783 (funcall 'target-fun 1 2))
1784 #-interpreter(test-target-fun-called #'caller-fun-1 3)
1786 (defun caller-fun-2 ()
1787 (declare (inline target-fun))
1788 (apply 'target-fun 1 '(3)))
1789 #-interpreter(test-target-fun-called #'caller-fun-2 4)
1791 (defun caller-fun-3 ()
1792 (flet ((target-fun (a b)
1793 (- a b)))
1794 (list (funcall #'target-fun 1 4) (funcall 'target-fun 1 4))))
1795 #-interpreter(test-target-fun-called #'caller-fun-3 (list -3 5))
1797 ;;; Reported by NIIMI Satoshi
1798 ;;; Subject: [Sbcl-devel] compilation error with optimization
1799 ;;; Date: Sun, 09 Apr 2006 17:36:05 +0900
1800 (defun test-minimal-debug-info-for-unstored-but-used-parameter (n a)
1801 (declare (optimize (speed 3)
1802 (debug 1)))
1803 (if (= n 0)
1805 (test-minimal-debug-info-for-unstored-but-used-parameter (1- n) a)))
1807 ;;; &KEY arguments with non-constant defaults.
1808 (declaim (notinline opaque-identity))
1809 (defun opaque-identity (x) x)
1810 (defstruct tricky-defaults
1811 (fun #'identity :type function)
1812 (num (opaque-identity 3) :type fixnum))
1813 (macrolet ((frob (form expected-expected-type)
1814 `(handler-case ,form
1815 (type-error (c) (assert (eq (type-error-expected-type c)
1816 ',expected-expected-type)))
1817 (:no-error (&rest vals) (error "~S returned values: ~S" ',form vals)))))
1818 (frob (make-tricky-defaults :fun 3) function)
1819 (frob (make-tricky-defaults :num #'identity) fixnum))
1821 (test-util:with-test (:name (compile &key :non-constant :default))
1822 (let ((fun (test-util:checked-compile
1823 '(lambda (&key (key (opaque-identity 3)))
1824 (declare (optimize safety) (type integer key))
1825 key))))
1826 (assert (= (funcall fun) 3))
1827 (assert (= (funcall fun :key 17) 17))
1828 (handler-case (funcall fun :key t)
1829 (type-error (c) (assert (eq (type-error-expected-type c) 'integer)))
1830 (:no-error (&rest vals) (declare (ignore vals)) (error "no error")))))
1832 ;;; Basic compiler-macro expansion
1833 (define-compiler-macro test-cmacro-0 () ''expanded)
1835 ;; The interpreter is not required to expand compiler-macros.
1836 ;; (Actually neither is the compiler!)
1837 #-interpreter(assert (eq 'expanded (funcall (lambda () (test-cmacro-0)))))
1839 ;;; FUNCALL forms in compiler macros, lambda-list parsing
1840 (define-compiler-macro test-cmacro-1
1841 (&whole whole a (a2) &optional b &rest c &key d)
1842 (list whole a a2 b c d))
1844 (macrolet ((test (form a a2 b c d)
1845 `(let ((form ',form))
1846 (destructuring-bind (whole a a2 b c d)
1847 (funcall (compiler-macro-function 'test-cmacro-1) form nil)
1848 (assert (equal whole form))
1849 (assert (eql a ,a))
1850 (assert (eql a2 ,a2))
1851 (assert (eql b ,b))
1852 (assert (equal c ,c))
1853 (assert (eql d ,d))))) )
1854 (test (funcall 'test-cmacro-1 1 (x) 2 :d 3) 1 'x 2 '(:d 3) 3)
1855 (test (test-cmacro-1 11 (y) 12 :d 13) 11 'y 12 '(:d 13) 13))
1857 ;;; FUNCALL forms in compiler macros, expansions
1858 (define-compiler-macro test-cmacro-2 () ''ok)
1860 #-interpreter(assert (eq 'ok (funcall (lambda () (funcall 'test-cmacro-2)))))
1861 #-interpreter(assert (eq 'ok (funcall (lambda () (funcall #'test-cmacro-2)))))
1863 ;;; Shadowing of compiler-macros by local functions
1864 (define-compiler-macro test-cmacro-3 () ''global)
1866 (defmacro find-cmacro-3 (&environment env)
1867 (compiler-macro-function 'test-cmacro-3 env))
1869 (assert (funcall (lambda () (find-cmacro-3))))
1870 (assert (not (funcall (lambda () (flet ((test-cmacro-3 ()))
1871 (find-cmacro-3))))))
1872 (assert (eq 'local (funcall (lambda () (flet ((test-cmacro-3 () 'local))
1873 (test-cmacro-3))))))
1874 (assert (eq 'local (funcall (lambda () (flet ((test-cmacro-3 () 'local))
1875 (funcall #'test-cmacro-3))))))
1876 #-interpreter
1877 (assert (eq 'global (funcall (lambda () (flet ((test-cmacro-3 () 'local))
1878 (funcall 'test-cmacro-3))))))
1880 ;;; Local NOTINLINE & INLINE
1881 (defun test-cmacro-4 () 'fun)
1882 (define-compiler-macro test-cmacro-4 () ''macro)
1884 (assert (eq 'fun (funcall (lambda ()
1885 (declare (notinline test-cmacro-4))
1886 (test-cmacro-4)))))
1888 #-interpreter
1889 (assert (eq 'macro (funcall (lambda ()
1890 (declare (inline test-cmacro-4))
1891 (test-cmacro-4)))))
1893 ;;; SETF function compiler macros
1894 (define-compiler-macro (setf test-cmacro-4) (&whole form value) ''ok)
1896 #-interpreter
1897 (assert (eq 'ok (funcall (lambda () (setf (test-cmacro-4) 'zot)))))
1898 #-interpreter
1899 (assert (eq 'ok (funcall (lambda () (funcall #'(setf test-cmacro-4) 'zot)))))
1901 ;;; Step instrumentation breaking type-inference
1902 (test-util:with-test (:name (compile :insert-step-conditions :type-inference))
1903 (assert (= 42 (funcall (test-util:checked-compile
1904 '(lambda (v x)
1905 (declare (optimize sb-c:insert-step-conditions))
1906 (if (typep (the function x) 'fixnum)
1907 (svref v (the function x))
1908 (funcall x))))
1909 nil (constantly 42)))))
1911 ;;; bug 368: array type intersections in the compiler
1912 (defstruct e368)
1913 (defstruct i368)
1914 (defstruct g368
1915 (i368s (make-array 0 :fill-pointer t) :type (or (vector i368) null)))
1916 (defstruct s368
1917 (g368 (error "missing :G368") :type g368 :read-only t))
1918 (declaim (ftype (function (fixnum (vector i368) e368) t) r368))
1919 (declaim (ftype (function (fixnum (vector e368)) t) h368))
1920 (defparameter *h368-was-called-p* nil)
1921 (defun nsu (vertices e368)
1922 (let ((i368s (g368-i368s (make-g368))))
1923 (let ((fuis (r368 0 i368s e368)))
1924 (format t "~&FUIS=~S~%" fuis)
1925 (or fuis (h368 0 i368s)))))
1926 (defun r368 (w x y)
1927 (declare (ignore w x y))
1928 nil)
1929 (defun h368 (w x)
1930 (declare (ignore w x))
1931 (setf *h368-was-called-p* t)
1932 (make-s368 :g368 (make-g368)))
1933 (let ((nsu (nsu #() (make-e368))))
1934 (format t "~&NSU returned ~S~%" nsu)
1935 (format t "~&*H368-WAS-CALLED-P*=~S~%" *h368-was-called-p*)
1936 (assert (s368-p nsu))
1937 (assert *h368-was-called-p*))
1939 ;;; bug 367: array type intersections in the compiler
1940 (defstruct e367)
1941 (defstruct i367)
1942 (defstruct g367
1943 (i367s (make-array 0 :fill-pointer t) :type (or (vector i367) null)))
1944 (defstruct s367
1945 (g367 (error "missing :G367") :type g367 :read-only t))
1946 (declaim (ftype (function ((vector i367) e367) (or s367 null)) r367))
1947 (declaim (ftype (function ((vector e367)) (values)) h367))
1948 (defun frob-367 (v w)
1949 (let ((x (g367-i367s (make-g367))))
1950 (let* ((y (or (r367 x w)
1951 (h367 x)))
1952 (z (s367-g367 y)))
1953 (format t "~&Y=~S Z=~S~%" y z)
1954 (g367-i367s z))))
1955 (defun r367 (x y) (declare (ignore x y)) nil)
1956 (defun h367 (x) (declare (ignore x)) (values))
1957 (assertoid:assert-error (frob-367 0 (make-e367)) type-error)
1959 (handler-case
1960 (delete-file (compile-file "circ-tree-test.lisp"))
1961 (storage-condition (e)
1962 (error e)))
1964 ;;; warnings due to step-instrumentation
1965 (defclass debug-test-class () ())
1966 (test-util:checked-compile
1967 '(lambda ()
1968 (declare (optimize (debug 3)))
1969 (defmethod print-object ((x debug-test-class) s)
1970 (call-next-method))))
1972 ;;; program-error from bad lambda-list keyword
1973 (test-util:with-test (:name (compile :bad lambda-list keyword program-error))
1974 (multiple-value-bind (fun failure-p)
1975 (test-util:checked-compile '(lambda (&whole x)
1976 (list &whole x))
1977 :allow-failure t)
1978 (assert failure-p)
1979 (assertoid:assert-error (funcall fun) program-error)))
1981 (test-util:with-test (:name (eval :bad lambda-list keyword program-error)
1982 :skipped-on (not :sb-eval))
1983 (assertoid:assert-error (let ((*evaluator-mode* :interpret))
1984 (funcall (eval '(lambda (&whole x)
1985 (list &whole x)))))
1986 program-error))
1988 ;;; ignore &environment
1989 (test-util:with-test (:name (defmacro ignore &environment))
1990 (test-util:checked-compile
1991 '(lambda ()
1992 (defmacro macro-ignore-env (&environment env)
1993 (declare (ignore env))
1994 :foo))))
1996 (test-util:with-test (:name (defmacro :no &environment))
1997 (test-util:checked-compile
1998 '(lambda ()
1999 (defmacro macro-no-env ()
2000 :foo))))
2002 (test-util:with-test (:name (disassemble :source-form))
2003 (dolist (*evaluator-mode* '(#+sb-eval :interpret :compile))
2004 (disassemble (eval '(defun disassemble-source-form-bug (x y z)
2005 (declare (optimize debug))
2006 (list x y z)))
2007 :stream (make-broadcast-stream))))
2009 ;;; long-standing bug in defaulting unknown values on the x86-64,
2010 ;;; since changing the calling convention (test case by Christopher
2011 ;;; Laux sbcl-help 30-06-2007)
2013 (defun default-values-bug-demo-sub ()
2014 (format t "test")
2015 nil)
2016 (compile 'default-values-bug-demo-sub)
2018 (defun default-values-bug-demo-main ()
2019 (multiple-value-bind (a b c d e f g h)
2020 (default-values-bug-demo-sub)
2021 (if a (+ a b c d e f g h) t)))
2022 (compile 'default-values-bug-demo-main)
2024 (test-util:with-test (:name (multiple-value-bind :default-values))
2025 (assert (default-values-bug-demo-main)))
2027 ;;; copy propagation bug reported by Paul Khuong
2029 (defun local-copy-prop-bug-with-move-arg (x)
2030 (labels ((inner ()
2031 (values 1 0)))
2032 (if x
2033 (inner)
2034 (multiple-value-bind (a b)
2035 (inner)
2036 (values b a)))))
2038 (test-util:with-test (:name (labels multiple-value-bind :copy-propagation))
2039 (assert (equal '(0 1) (multiple-value-list
2040 (local-copy-prop-bug-with-move-arg nil))))
2041 (assert (equal '(1 0) (multiple-value-list
2042 (local-copy-prop-bug-with-move-arg t)))))
2044 ;;;; with-pinned-objects & unwind-protect, using all non-tail conventions
2046 (defun wpo-quux () (list 1 2 3))
2047 (defvar *wpo-quux* #'wpo-quux)
2049 (defun wpo-call ()
2050 (unwind-protect
2051 (sb-sys:with-pinned-objects (*wpo-quux*)
2052 (values (funcall *wpo-quux*)))))
2053 (assert (equal '(1 2 3) (wpo-call)))
2055 (defun wpo-multiple-call ()
2056 (unwind-protect
2057 (sb-sys:with-pinned-objects (*wpo-quux*)
2058 (funcall *wpo-quux*))))
2059 (assert (equal '(1 2 3) (wpo-multiple-call)))
2061 (defun wpo-call-named ()
2062 (unwind-protect
2063 (sb-sys:with-pinned-objects (*wpo-quux*)
2064 (values (wpo-quux)))))
2065 (assert (equal '(1 2 3) (wpo-call-named)))
2067 (defun wpo-multiple-call-named ()
2068 (unwind-protect
2069 (sb-sys:with-pinned-objects (*wpo-quux*)
2070 (wpo-quux))))
2071 (assert (equal '(1 2 3) (wpo-multiple-call-named)))
2073 (defun wpo-call-variable (&rest args)
2074 (unwind-protect
2075 (sb-sys:with-pinned-objects (*wpo-quux*)
2076 (values (apply *wpo-quux* args)))))
2077 (assert (equal '(1 2 3) (wpo-call-variable)))
2079 (defun wpo-multiple-call-variable (&rest args)
2080 (unwind-protect
2081 (sb-sys:with-pinned-objects (*wpo-quux*)
2082 (apply #'wpo-quux args))))
2083 (assert (equal '(1 2 3) (wpo-multiple-call-named)))
2085 (defun wpo-multiple-call-local ()
2086 (flet ((quux ()
2087 (wpo-quux)))
2088 (unwind-protect
2089 (sb-sys:with-pinned-objects (*wpo-quux*)
2090 (quux)))))
2091 (assert (equal '(1 2 3) (wpo-multiple-call-local)))
2093 ;;; bug 417: toplevel NIL confusing source path logic
2094 (handler-case
2095 (delete-file (let ((*error-output* (make-broadcast-stream)))
2096 (compile-file "bug-417.lisp" :verbose nil :print nil)))
2097 (sb-ext:code-deletion-note (e)
2098 (error e)))
2100 ;;; unknown values return convention getting disproportionate
2101 ;;; amounts of values.
2102 (declaim (notinline one-value two-values))
2103 (defun one-value (x)
2104 (not x))
2105 (defun two-values (x y)
2106 (values y x))
2107 (defun wants-many-values (x y)
2108 (multiple-value-bind (a b c d e f)
2109 (one-value y)
2110 (assert (and (eql (not y) a)
2111 (not (or b c d e f)))))
2112 (multiple-value-bind (a b c d e f)
2113 (two-values y x)
2114 (assert (and (eql a x) (eql b y)
2115 (not (or c d e f)))))
2116 (multiple-value-bind (a b c d e f g h i)
2117 (one-value y)
2118 (assert (and (eql (not y) a)
2119 (not (or b c d e f g h i)))))
2120 (multiple-value-bind (a b c d e f g h i)
2121 (two-values y x)
2122 (assert (and (eql a x) (eql b y)
2123 (not (or c d e f g h i)))))
2124 (multiple-value-bind (a b c d e f g h i j k l m n o p q r s)
2125 (one-value y)
2126 (assert (and (eql (not y) a)
2127 (not (or b c d e f g h i j k l m n o p q r s)))))
2128 (multiple-value-bind (a b c d e f g h i j k l m n o p q r s)
2129 (two-values y x)
2130 (assert (and (eql a x) (eql b y)
2131 (not (or c d e f g h i j k l m n o p q r s))))))
2132 (wants-many-values 1 42)
2134 ;;; constant coalescing
2136 (defun count-code-constants (x f)
2137 (let ((code (sb-kernel:fun-code-header f))
2138 (n 0))
2139 (loop for i from sb-vm:code-constants-offset below (sb-kernel:code-header-words code)
2140 do (when (equal x (sb-kernel:code-header-ref code i))
2141 (incf n)))
2144 (defvar *lambda*)
2146 (defun compile2 (lambda)
2147 (let* ((lisp "compiler-impure-tmp.lisp")
2148 (fasl (compile-file-pathname lisp)))
2149 (unwind-protect
2150 (progn
2151 (with-open-file (f lisp :direction :output)
2152 (prin1 `(setf *lambda* ,lambda) f))
2153 (multiple-value-bind (fasl warn fail)
2154 (compile-file lisp :verbose nil :print nil)
2155 (declare (ignore warn))
2156 (when fail
2157 (error "File-compiling ~S failed." lambda))
2158 (let ((*lambda* nil))
2159 (load fasl)
2160 (values *lambda* (test-util:checked-compile lambda)))))
2161 (ignore-errors (delete-file lisp))
2162 (ignore-errors (delete-file fasl)))))
2164 ;; named and unnamed
2165 (defconstant +born-to-coalesce+ '.born-to-coalesce.)
2166 (multiple-value-bind (file-fun core-fun)
2167 (compile2 '(lambda ()
2168 (let ((x (cons +born-to-coalesce+ nil))
2169 (y (cons '.born-to-coalesce. nil)))
2170 (list x y))))
2171 (assert (= 1 (count-code-constants '.born-to-coalesce. file-fun)))
2172 (assert (= 1 (count-code-constants '.born-to-coalesce. core-fun))))
2174 ;; some things must retain identity under COMPILE, but we want to coalesce them under COMPILE-FILE
2175 (defun assert-coalescing (constant)
2176 (let ((value (copy-seq (symbol-value constant))))
2177 (multiple-value-bind (file-fun core-fun)
2178 (compile2 `(lambda ()
2179 (let ((x (cons ,constant nil))
2180 (y (cons ',value nil)))
2181 (list x y))))
2182 (assert (= 1 (count-code-constants value file-fun)))
2183 (assert (= 2 (count-code-constants value core-fun)))
2184 (let* ((l (funcall file-fun))
2185 (a (car (first l)))
2186 (b (car (second l))))
2187 (assert (and (equal value a)
2188 (equal a b)
2189 (eq a b))))
2190 (let* ((l (funcall core-fun))
2191 (a (car (first l)))
2192 (b (car (second l))))
2193 (assert (and (equal value a)
2194 (equal a b)
2195 (not (eq a b))))))))
2197 (defconstant +born-to-coalesce2+ "maybe coalesce me!")
2198 (assert-coalescing '+born-to-coalesce2+)
2200 (defconstant +born-to-coalesce3+ #*01101001011101110100011)
2201 (assert-coalescing '+born-to-coalesce3+)
2203 (defconstant +born-to-coalesce4+ '(foo bar "zot" 123 (nested "quux") #*0101110010))
2204 (assert-coalescing '+born-to-coalesce4+)
2206 (defclass some-constant-thing () ())
2208 ;;; correct handling of nested things loaded via SYMBOL-VALUE
2209 (defvar *sneaky-nested-thing* (list (make-instance 'some-constant-thing)))
2210 (defconstant +sneaky-nested-thing+ *sneaky-nested-thing*)
2211 (multiple-value-bind (file-fun core-fun) (compile2 '(lambda () +sneaky-nested-thing+))
2212 (assert (equal *sneaky-nested-thing* (funcall file-fun)))
2213 (assert (equal *sneaky-nested-thing* (funcall core-fun))))
2215 ;;; catch constant modifications thru undefined variables
2216 (defun sneak-set-dont-set-me (x)
2217 (ignore-errors (setq dont-set-me x)))
2218 (defconstant dont-set-me 42)
2219 (assert (not (sneak-set-dont-set-me 13)))
2220 (assert (= 42 dont-set-me))
2221 (defun sneak-set-dont-set-me2 (x)
2222 (ignore-errors (setq dont-set-me2 x)))
2223 (defconstant dont-set-me2 (make-instance 'some-constant-thing))
2224 (assert (not (sneak-set-dont-set-me2 13)))
2225 (assert (typep dont-set-me2 'some-constant-thing))
2227 ;;; check that non-trivial constants are EQ across different files: this is
2228 ;;; not something ANSI either guarantees or requires, but we want to do it
2229 ;;; anyways.
2230 (defconstant +share-me-1+ #-inline-constants 123.456d0 #+inline-constants nil)
2231 (defconstant +share-me-2+ "a string to share")
2232 (defconstant +share-me-3+ (vector 1 2 3))
2233 (defconstant +share-me-4+ (* 2 most-positive-fixnum))
2234 (multiple-value-bind (f1 c1) (compile2 '(lambda () (values +share-me-1+
2235 +share-me-2+
2236 +share-me-3+
2237 +share-me-4+
2238 #-inline-constants pi)))
2239 (multiple-value-bind (f2 c2) (compile2 '(lambda () (values +share-me-1+
2240 +share-me-2+
2241 +share-me-3+
2242 +share-me-4+
2243 #-inline-constants pi)))
2244 (flet ((test (fa fb)
2245 (mapc (lambda (a b)
2246 (assert (eq a b)))
2247 (multiple-value-list (funcall fa))
2248 (multiple-value-list (funcall fb)))))
2249 (test f1 c1)
2250 (test f1 f2)
2251 (test f1 c2))))
2253 ;;; user-defined satisfies-types cannot be folded
2254 (deftype mystery () '(satisfies mysteryp))
2255 (defvar *mystery* nil)
2256 (defun mysteryp (x) (eq x *mystery*))
2257 (defstruct thing (slot (error "missing") :type mystery))
2258 (defun test-mystery (m) (when (eq :mystery (thing-slot m)) :ok))
2259 (setf *mystery* :mystery)
2260 (assert (eq :ok (test-mystery (make-thing :slot :mystery))))
2262 ;;; Singleton types can also be constant.
2263 (test-util:with-test (:name :propagate-singleton-types-to-eql)
2264 (macrolet ((test (type value &aux (fun (gensym "FUN")))
2265 `(progn
2266 (declaim (ftype (function () (values ,type &optional)) ,fun))
2267 (defun ,fun ()
2268 ',value)
2269 (lambda (x)
2270 (if (eql x (,fun))
2272 (eql x (,fun)))))))
2273 (values
2274 (test (eql foo) foo)
2275 (test (integer 0 0) 0)
2276 (test (double-float 0d0 0d0) 0d0)
2277 (test (eql #\c) #\c))))
2279 (declaim (ftype (function () (integer 42 42)) bug-655581))
2280 (defun bug-655581 ()
2282 (declaim (notinline bug-655581))
2283 (test-util:with-test (:name :bug-655581)
2284 (multiple-value-bind (type derived)
2285 (funcall (test-util:checked-compile
2286 `(lambda ()
2287 (ctu:compiler-derived-type (bug-655581)))))
2288 (assert derived)
2289 (assert (equal '(integer 42 42) type))))
2291 (test-util:with-test (:name :clear-derived-types-on-set-fdefn)
2292 (let ((*evaluator-mode* :compile)
2293 (*derive-function-types* t))
2294 (eval `(progn
2295 (defun clear-derived-types-on-set-fdefn-1 ()
2296 "foo")
2297 (setf (symbol-function 'clear-derived-types-on-set-fdefn-1)
2298 (constantly "foobar"))
2299 (defun clear-derived-types-on-set-fdefn-2 ()
2300 (length (clear-derived-types-on-set-fdefn-1)))))
2301 (assert (= 6 (clear-derived-types-on-set-fdefn-2)))))
2303 (test-util:with-test (:name (:bug-655126 :derive-function-types t))
2304 (let ((*evaluator-mode* :compile)
2305 (*derive-function-types* t))
2306 (eval `(defun bug-655126 (x) x))
2307 ;; Full warnings are ok due to *derive-function-types* = T.
2308 (assert (eq :full-warning
2309 (handler-case
2310 (eval `(defun bug-655126-2 ()
2311 (bug-655126)))
2312 ((and warning (not style-warning)) ()
2313 :full-warning))))
2314 (assert (eq 'bug-655126
2315 (handler-case
2316 (eval `(defun bug-655126 (x y)
2317 (cons x y)))
2318 ((and warning (not sb-kernel:redefinition-warning)) ()
2319 :oops))))
2320 (assert (eq :full-warning
2321 (handler-case
2322 (eval `(defun bug-655126 (x)
2323 (bug-655126 x y)))
2324 ((and warning
2325 (not style-warning)
2326 (not sb-kernel:redefinition-warning)) ()
2327 :full-warning))))))
2329 (test-util:with-test (:name (:bug-655126 :derive-function-types nil))
2330 (let ((*evaluator-mode* :compile))
2331 (eval `(defun bug-655126/b (x) x))
2332 ;; Just style-warning here.
2333 (assert (eq :style-warning
2334 (handler-case
2335 (eval `(defun bug-655126-2/b ()
2336 (bug-655126/b)))
2337 (style-warning ()
2338 :style-warning))))
2339 (assert (eq 'bug-655126/b
2340 (handler-case
2341 (eval `(defun bug-655126/b (x y)
2342 (cons x y)))
2343 ((and warning (not sb-kernel:redefinition-warning)) ()
2344 :oops))))
2345 ;; Bogus self-call is always worth a full one.
2346 (assert (eq :full-warning
2347 (handler-case
2348 (eval `(defun bug-655126/b (x)
2349 (bug-655126/b x y)))
2350 ((and warning
2351 (not style-warning)
2352 (not sb-kernel:redefinition-warning)) ()
2353 :full-warning))))))
2355 (test-util:with-test (:name :bug-657499)
2356 ;; Don't trust derived types within the compilation unit.
2357 (ctu:file-compile
2358 `((declaim (optimize safety))
2359 (defun bug-657499-foo ()
2360 (cons t t))
2361 (defun bug-657499-bar ()
2362 (let ((cons (bug-657499-foo)))
2363 (setf (car cons) 3)
2364 cons)))
2365 :load t)
2366 (locally (declare (optimize safety))
2367 (setf (symbol-function 'bug-657499-foo) (constantly "foobar"))
2368 (assert (eq :type-error
2369 (handler-case
2370 (funcall 'bug-657499-bar)
2371 (type-error (e)
2372 (assert (eq 'cons (type-error-expected-type e)))
2373 (assert (equal "foobar" (type-error-datum e)))
2374 :type-error))))))
2376 (declaim (unsigned-byte *symbol-value-test-var*))
2377 (defvar *symbol-value-test-var*)
2379 (declaim (unsigned-byte **global-symbol-value-test-var**))
2380 (defglobal **global-symbol-value-test-var** 0)
2382 (test-util:with-test (:name :symbol-value-type-derivation)
2383 (let ((fun (compile nil `(lambda () *symbol-value-test-var*))))
2384 (assert (equal '(function () (values unsigned-byte &optional))
2385 (%simple-fun-type fun))))
2386 (let ((fun (compile nil `(lambda () **global-symbol-value-test-var**))))
2387 (assert (equal '(function () (values unsigned-byte &optional))
2388 (%simple-fun-type fun))))
2389 (let ((ufix (type-specifier (specifier-type `(and unsigned-byte fixnum)))))
2390 ;; Test a free type decl
2391 (let ((fun (compile nil `(lambda ()
2392 (declare (fixnum *symbol-value-test-var*))
2393 (symbol-value '*symbol-value-test-var*)))))
2394 (assert (equal `(function () (values ,ufix &optional))
2395 (%simple-fun-type fun))))
2396 ;; Test a bound type decl
2397 (let ((fun (compile nil `(lambda (*symbol-value-test-var*)
2398 (declare (fixnum *symbol-value-test-var*))
2399 (symbol-value '*symbol-value-test-var*)))))
2400 (assert (equal `(function (,ufix) (values ,ufix &optional))
2401 (%simple-fun-type fun)))))
2402 (let ((fun (compile
2404 `(lambda ()
2405 (declare (fixnum **global-symbol-value-test-var**))
2406 (symbol-global-value '**global-symbol-value-test-var**))))
2407 (ufix (type-specifier (specifier-type `(and unsigned-byte fixnum)))))
2408 (assert (equal `(function () (values ,ufix &optional))
2409 (%simple-fun-type fun)))))
2411 (test-util:with-test (:name :mv-bind-to-let-type-propagation)
2412 (let ((f (test-util:checked-compile
2413 `(lambda (x)
2414 (declare (optimize speed)
2415 (type (integer 20 50) x))
2416 (< (truncate x 10) 1))))
2417 (g (test-util:checked-compile
2418 `(lambda (x)
2419 (declare (optimize speed)
2420 (type (integer 20 50) x))
2421 (< (nth-value 1 (truncate x 10)) 10))))
2422 (h (test-util:checked-compile
2423 `(lambda (x)
2424 (declare (optimize speed)
2425 (type (integer 20 50) x))
2426 (multiple-value-bind (q r)
2427 (truncate x 10)
2428 (declare (ignore r))
2429 (< q 1)))))
2430 (type0 '(function ((integer 20 50)) (values null &optional)))
2431 (type1 '(function ((integer 20 50)) (values (member t) &optional))))
2432 (assert (equal type0 (sb-kernel:%simple-fun-type f)))
2433 (assert (equal type1 (sb-kernel:%simple-fun-type g)))
2434 (assert (equal type0 (sb-kernel:%simple-fun-type h)))))
2436 (test-util:with-test (:name :bug-308921)
2437 (let ((*check-consistency* t))
2438 (ctu:file-compile
2439 `((let ((exported-symbols-alist
2440 (loop for symbol being the external-symbols of :cl
2441 collect (cons symbol
2442 (concatenate 'string
2444 (string-downcase symbol))))))
2445 (defun hyperdoc-lookup (symbol)
2446 (cdr (assoc symbol exported-symbols-alist)))))
2447 :load nil)))
2449 (test-util:with-test (:name :bug-308941)
2450 (multiple-value-bind (warn fail)
2451 (let ((*check-consistency* t))
2452 (ctu:file-compile
2453 "(eval-when (:compile-toplevel :load-toplevel :execute)
2454 (defstruct foo3))
2455 (defstruct bar
2456 (foo #.(make-foo3)))"
2457 :load nil))
2458 ;; ...but the compiler should not break.
2459 (assert (and warn fail))))
2461 (test-util:with-test (:name :bug-903821)
2462 (let* ((fun (test-util:checked-compile
2463 '(lambda (x n)
2464 (declare (sb-ext:word x)
2465 (type (integer 0 #.(1- sb-vm:n-machine-word-bits)) n)
2466 (optimize speed))
2467 (logandc2 x (ash -1 n)))))
2468 (thing-not-to-call
2469 (intern (format nil "ASH-LEFT-MOD~D" sb-vm::n-machine-word-bits) "SB-VM")))
2470 (assert (not (member (symbol-function thing-not-to-call)
2471 (ctu:find-named-callees fun))))
2472 (assert (= 7 (funcall fun 15 3)))))
2474 (test-util:with-test (:name :bug-997528)
2475 (let ((fun (test-util:checked-compile
2476 '(lambda (x)
2477 (declare (optimize (speed 0) (space 0))
2478 (type (integer -228645653448155482 -228645653447928749) x))
2479 (floor 1.0 (the (integer -228645653448151677 -228645653448150900) x))))))
2480 (multiple-value-bind (quo rem)
2481 (funcall fun -228645653448151381)
2482 (assert (= quo -1))
2483 (assert (= rem (float -228645653448151381))))))
2485 (defmacro def-many-code-constants ()
2486 `(defun many-code-constants ()
2487 ,@(loop for i from 0 below 1000
2488 collect `(print ,(format nil "hi-~d" i)))))
2490 (test-util:with-test (:name :many-code-constants)
2491 (def-many-code-constants)
2492 (assert (search "hi-999"
2493 (with-output-to-string (*standard-output*)
2494 (many-code-constants)))))
2496 (test-util:with-test (:name :bug-943953)
2497 ;; we sometimes splice compiler structures like clambda in
2498 ;; source, and our error reporting would happily use that
2499 ;; as source forms.
2500 (let* ((src "bug-943953.lisp")
2501 (obj (compile-file-pathname src)))
2502 (unwind-protect (let ((*error-output* (make-broadcast-stream)))
2503 (compile-file src :verbose nil :print nil))
2504 (ignore-errors (delete-file obj)))))
2506 (declaim (inline vec-1177703))
2507 (defstruct (vec-1177703 (:constructor vec-1177703 (&optional x)))
2508 (x 0.0d0 :type double-float))
2510 (declaim (inline norm-1177703))
2511 (defun norm-1177703 (v)
2512 (vec-1177703 (sqrt (vec-1177703-x v))))
2514 (test-util:with-test (:name :bug-1177703)
2515 (test-util:checked-compile `(lambda (x)
2516 (norm-1177703 (vec-1177703 x)))))
2518 (declaim (inline call-1035721))
2519 (defun call-1035721 (function)
2520 (lambda (x)
2521 (funcall function x)))
2523 (declaim (inline identity-1035721))
2524 (defun identity-1035721 (x)
2527 (test-util:with-test (:name :bug-1035721)
2528 (test-util:checked-compile
2529 `(lambda ()
2530 (list
2531 (call-1035721 #'identity-1035721)
2532 (lambda (x)
2533 (identity-1035721 x))))))
2535 (test-util:with-test (:name :expt-type-derivation-and-method-redefinition)
2536 (defmethod expt-type-derivation ((x list) &optional (y 0.0))
2537 (declare (type float y))
2538 (expt 2 y))
2539 ;; the redefinition triggers a type lookup of the old
2540 ;; fast-method-function's type, which had a bogus type specifier of
2541 ;; the form (double-float 0) from EXPT type derivation
2542 (defmethod expt-type-derivation ((x list) &optional (y 0.0))
2543 (declare (type float y))
2544 (expt 2 y)))
2546 ;; Lp# 1066451 - declarations were either misplaced or dropped
2547 ;; depending on whether the :policy argument was used in DEFTRANSFORM.
2548 ;; That was a bit random. :policy doesn't affect whether decls
2549 ;; are accepted now.
2550 (defun foo (blah)
2551 (declare (special randomness-factor))
2552 (if (constant-lvar-p randomness-factor)
2553 (format nil "Weird transform answer is ~D"
2554 (+ (lvar-value randomness-factor) blah))))
2555 (defknown weird-fn (integer symbol &key (:magic real)) t)
2556 (deftransform weird-fn ((x s &key ((:magic randomness-factor)))
2557 (fixnum t &key (:magic fixnum)))
2558 ;; I can't see much use for declarations other than SPECIAL here,
2559 ;; but we shouldn't supposedly allow them and then not handle them right.
2560 (declare (special fred) (special randomness-factor) (lvar x s))
2561 (foo fred))
2562 (test-util:with-test (:name :deftransform-bug-1066451)
2563 (let ((f (let ((fred 3))
2564 (declare (special fred))
2565 (test-util:checked-compile
2566 '(lambda () (weird-fn 2 'foo :magic 11))))))
2567 (assert (string= (funcall f)
2568 "Weird transform answer is 14"))))
2570 (defun skip-1-passthrough (a b sb-int:&more context count)
2571 (declare (ignore a b))
2572 (multiple-value-call 'list
2573 'start
2574 (sb-c::%more-arg-values context 1 (1- (truly-the fixnum count)))
2575 'end))
2576 (defun skip-2-passthrough (a b sb-int:&more context count)
2577 (declare (ignore a b))
2578 (multiple-value-call 'list
2579 'start
2580 (sb-c::%more-arg-values context 2 (- (truly-the fixnum count) 2))
2581 'end))
2582 (defun skip-n-passthrough (n-skip n-copy sb-int:&more context count)
2583 (assert (>= count (+ n-copy n-skip))) ; prevent crashes
2584 (multiple-value-call 'list
2585 'start
2586 (sb-c::%more-arg-values context n-skip n-copy)
2587 'end))
2589 ;; %MORE-ARG-VALUES was wrong on x86 and x86-64 with nonzero 'skip'.
2590 ;; It's entirely possible that other backends are also not working.
2591 (test-util:with-test (:name :more-arg-fancy
2592 :skipped-on :interpreter)
2593 (assert (equal (skip-1-passthrough 0 0 'a 'b 'c 'd 'e 'f)
2594 '(start b c d e f end)))
2595 (assert (equal (skip-2-passthrough 0 0 'a 'b 'c 'd 'e 'f)
2596 '(start c d e f end)))
2597 (assert (equal (skip-n-passthrough 1 5 'a 'b 'c 'd 'e 'f)
2598 '(start b c d e f end)))
2599 (assert (equal (skip-n-passthrough 1 5 'a 'b 'c 'd 'e 'f 'g)
2600 '(start b c d e f end)))
2601 (assert (equal (skip-n-passthrough 2 5 'a 'b 'c 'd 'e 'f 'g)
2602 '(start c d e f g end)))
2603 (assert (equal (skip-n-passthrough 2 5 'a 'b 'c 'd 'e 'f 'g 'h)
2604 '(start c d e f g end))))
2606 (test-util:with-test (:name :macro-policy)
2607 (flet ((count-notes ()
2608 (let ((count 0))
2609 (handler-bind ((compiler-note
2610 (lambda (c)
2612 (incf count)
2613 (muffle-warning))))
2614 (multiple-value-bind (fasl warnings errors)
2615 (compile-file "macro-policy-test.lisp"
2616 :print nil :verbose nil)
2617 (ignore-errors (delete-file fasl))
2618 (assert (and (not warnings) (not errors)))
2619 count)))))
2620 (let* ((baseline (count-notes))
2621 (test (progv '(*frob-macro-policy*) '(t) (count-notes)))
2622 (baseline-again (count-notes)))
2623 (assert (/= 0 baseline))
2624 (assert (= 0 test))
2625 ;; macro-policy is rebound inside compile-file
2626 (assert (= baseline-again baseline)))))
2628 (in-package :cl-user)
2630 (with-test (:name :merge-lambdas-dead-return)
2631 (let ((fasl (let ((*error-output* (make-broadcast-stream)))
2632 (compile-file "merge-lambdas.lisp"
2633 :print nil :verbose nil))))
2634 (ignore-errors (delete-file fasl))))
2636 (declaim (inline ensure-a-fun))
2637 (defun ensure-a-fun (f) (coerce f 'function))
2638 (defmacro compose2 (f g)
2639 `(let ((f (ensure-a-fun ,f))
2640 (g (ensure-a-fun ,g)))
2641 (lambda (arg) (funcall f (funcall g arg)))))
2643 (with-test (:name :coerce-to-function-smarter)
2644 (let ((f (checked-compile
2645 '(lambda (x)
2646 (funcall (compose2 #'integerp #'car) x)))))
2647 ;; should be completely inlined
2648 (assert (null (ctu:find-named-callees f)))))
2650 (with-test (:name :derived-function-type-casts)
2651 (let ((fasl (compile-file "derived-function-type-casts.lisp"
2652 :print nil :verbose nil)))
2653 (load fasl)
2654 (ignore-errors (delete-file fasl))
2655 (assert (null (funcall 'derived-function-type-casts)))))
2657 (with-test (:name (compile function :invalid-function-name))
2658 (flet ((test-case (nameoid)
2659 (assert (nth-value
2660 1 (checked-compile `(lambda () (function ,nameoid))
2661 :allow-failure t)))))
2662 (test-case 1)
2663 (test-case "foo")
2664 (test-case '(foo bar))))
2666 (defun catch-compiled-program-error (form &rest args)
2667 (multiple-value-bind (function failure-p)
2668 (checked-compile form :allow-failure t :allow-warnings t)
2669 (assert failure-p)
2670 (assert-error (apply function args))))
2672 (with-test (:name :duplicate-&key-no-error)
2673 (catch-compiled-program-error
2674 '(lambda () (defun duplicate-&key-no-error (&key a a) a))))
2676 (with-test (:name :bad-type-specifiers)
2677 (catch-compiled-program-error
2678 '(lambda (x) (typep x '(values 10)))
2680 (catch-compiled-program-error
2681 '(lambda () (declare (sb-ext:muffle-conditions 10)))))
2683 (with-test (:name :coverage-and-errors)
2684 (ctu:file-compile
2685 '((locally (declare (optimize sb-c:store-coverage-data))
2686 (1)))))
2688 (symbol-macrolet ((x 30))
2689 (macrolet ((foo (y) (+ x y)))
2690 (declaim (inline environment-around-inline))
2691 (defun environment-around-inline (z)
2692 (* z (foo 4)))))
2694 (with-test (:name :environment-around-inline)
2695 (defun environment-around-inline.2 (z)
2696 (environment-around-inline z))
2697 (assert (= (environment-around-inline.2 10) 340)))
2699 (with-test (:name :defun-setf-return-value)
2700 (let ((name `(setf ,(gensym))))
2701 (assert (equal (eval `(defun ,name ()))
2702 name))))
2704 (with-test (:name :make-sequence-unknown)
2705 (let ((fun (checked-compile
2706 `(lambda (x)
2707 (let ((vector (make-sequence '(simple-array make-sequence-unknown (*)) 10)))
2708 (setf (aref vector 0) x)
2709 vector))
2710 :allow-style-warnings t)))
2711 (deftype make-sequence-unknown () 'fixnum)
2712 (assert-error (funcall fun 'abc) type-error)))
2714 (with-test (:name (:compiler-messages function :type-specifier))
2715 ;; Previously, function types were often printed confusingly, e.g.:
2717 ;; (function ()) => #'NIL
2718 ;; (function *) => #'*
2719 ;; (function (function a)) => #'#'A
2721 (flet ((test-case (spec)
2722 (destructuring-bind (type expected) spec
2723 (unwind-protect
2724 (let ((report))
2725 (proclaim '(ftype (function () boolean) my-function))
2726 (handler-bind ((warning
2727 (lambda (condition)
2728 (setf report (princ-to-string condition))
2729 (muffle-warning))))
2730 (proclaim `(ftype ,type my-function)))
2731 (assert (search expected report)))
2732 (fmakunbound 'my-function)))))
2733 (mapc
2734 #'test-case
2735 `(((function ()) "(FUNCTION NIL)")
2736 ((function *) "(FUNCTION *)")
2737 ((function (function *)) "(FUNCTION (FUNCTION *))")
2738 ((function (function (eql 1))) "(FUNCTION (FUNCTION (EQL 1))")))))
2740 (with-test (:name :boxed-ref-setf-special)
2741 (let* ((var (gensym))
2742 (fun (checked-compile `(lambda ()
2743 (declare (special ,var))
2744 (setf ,var 10d0)))))
2745 (ctu:assert-no-consing (funcall fun))))
2747 (with-test (:name :boxed-ref-bind-special)
2748 (let* ((var (gensym))
2749 (fun (checked-compile `(lambda ()
2750 (let ((,var 10d0))
2751 (declare (special ,var)))))))
2752 (ctu:assert-no-consing (funcall fun))))
2754 (with-test (:name :boxed-ref-svref)
2755 (let ((fun (checked-compile `(lambda (x)
2756 (setf (svref x 0) 10d0))))
2757 (vector (vector nil)))
2758 (ctu:assert-no-consing (funcall fun vector))))
2760 (with-test (:name :boxed-ref-instance-set)
2761 (let* ((name (gensym "STRUCT"))
2762 (fun (progn
2763 (eval `(defstruct ,name x))
2764 (checked-compile `(lambda (x)
2765 (setf (,(sb-int:symbolicate name '-x) x)
2766 10d0)))))
2767 (instance (funcall (sb-int:symbolicate 'make- name))))
2768 (ctu:assert-no-consing (funcall fun instance))))
2770 (with-test (:name :boxed-ref-car)
2771 (let ((fun (checked-compile `(lambda (x)
2772 (setf (car x) 10d0)
2773 (setf (cdr x) 10d0))))
2774 (list (list nil)))
2775 (ctu:assert-no-consing (funcall fun list))))
2778 (with-test (:name :ftype-return-type-conflict)
2779 (declaim (ftype (function () fixnum) ftype-return-type-conflict))
2780 (assert-error (funcall (checked-compile `(sb-int:named-lambda ftype-return-type-conflict () nil)
2781 :allow-warnings t
2782 :allow-failure t))
2783 type-error))