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