1 ;;;; various compiler tests without side effects
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; While most of SBCL is derived from the CMU CL system, the test
7 ;;;; files (like this one) were written from scratch after the fork
10 ;;;; This software is in the public domain and is provided with
11 ;;;; absolutely no warranty. See the COPYING and CREDITS files for
12 ;;;; more information.
14 ;;;; This file of tests was added because the tests in 'compiler.pure.lisp'
15 ;;;; are a total hodgepodge- there is often no hugely compelling reason for
16 ;;;; their being tests of the compiler per se, such as whether
17 ;;;; INPUT-ERROR-IN-COMPILED-FILE is a subclass of SERIOUS-CONDITION;
18 ;;;; in addition to which it is near impossible to wade through the
19 ;;;; ton of nameless, slow, and noisy tests.
21 ;;;; This file strives to do better on all fronts:
22 ;;;; the tests should be fast, named, and not noisy.
24 (cl:in-package
:cl-user
)
26 (load "compiler-test-util.lisp")
28 (with-test (:name
:ldb-recognize-local-macros
)
29 ;; Should not call %LDB
30 (assert (not (ctu:find-named-callees
33 (declare (optimize speed
))
34 (macrolet ((b () '(byte 2 2)))
35 (ldb (b) (the fixnum x
)))))))))
38 (with-test (:name
:dbp-eval-order
)
39 (sb-int:collect
((calls))
41 (dpb (progn (calls 'eval-new
) new
)
42 (progn (calls 'eval-byte
) (byte 10 10))
43 (progn (calls 'eval-old
) old
))))
45 (assert (equal (calls)
46 '(eval-new eval-byte eval-old
))))))
48 ;; Best practice treats TRULY-THE as a special operator, not a macro,
49 ;; in a context such as (DPB X (TRULY-THE SB-KERNEL:BYTE-SPECIFIER ...) Y).
50 ;; DPB used to expand its second argument using MACROEXPAND and lose
51 ;; the nuance of TRULY-THE. Strictly speaking, byte-specifier is not a
52 ;; type specifier that users are supposed to know about, so portable code
53 ;; should not care, but this might affect internal code.
54 (with-test (:name
:dpb-inner-macro
)
55 (flet ((source-xform (sexpr)
56 (funcall (sb-int:info
:function
:source-transform
(car sexpr
))
57 sexpr
(sb-kernel:make-null-lexenv
))))
58 (assert (equal-mod-gensyms
60 '(dpb (new) (truly-the sb-kernel
:byte-specifier bspec
) (old)))
62 (byte (truly-the sb-kernel
:byte-specifier bspec
)))
63 (sb-kernel:%dpb new
(byte-size byte
) (byte-position byte
)
66 (with-test (:name
:inline-satisfies-predicate
)
67 ;; If we remove the indirections in these functions,
68 ;; this test should visibly break so that we can write a new test
69 ;; that asserts that inlining F works in (THE (SATISFIES F) obj).
70 (assert (equal (sb-ext:typexpand
'sb-impl
::function-name
)
71 '(satisfies sb-int
:legal-fun-name-p
)))
72 (let ((f (compile nil
'(lambda (x) (the sb-impl
::function-name x
)))))
73 (assert (equal (list (symbol-function 'sb-int
:valid-function-name-p
))
74 (ctu:find-named-callees f
))))
75 (let ((f (compile nil
'(lambda (x)
76 (declare (notinline sb-int
:legal-fun-name-p
))
77 (the sb-impl
::function-name x
)))))
78 (assert (equal (list (symbol-function 'sb-int
:legal-fun-name-p
))
79 (ctu:find-named-callees f
)))))
81 (with-test (:name
:make-array-untestable-type-no-warning
)
83 (compile nil
`(lambda () (make-array '(2 2)
84 :element-type
`(satisfies foofa
))))))
86 (with-test (:name
:make-array-nil-no-warning
)
88 (compile nil
'(lambda () (make-array '(2 2) :element-type nil
)))))
90 (with-test (:name
:nth-value-huge-n-works
)
91 (flet ((return-a-ton-of-values ()
92 (values-list (loop for i below
5000 collect i
))))
93 (assert (= (nth-value 1 (return-a-ton-of-values)) 1))
94 (assert (= (nth-value 4000 (return-a-ton-of-values)) 4000))))
96 (defstruct (a-test-structure-foo
97 (:constructor make-a-foo-1
)
98 (:constructor make-a-foo-2
(b &optional a
)))
100 (b nil
:type integer
))
102 (with-test (:name
:improperly-initialized-slot-warns
)
103 (with-open-stream (*error-output
* (make-broadcast-stream))
104 (multiple-value-bind (f warn err
)
105 (compile nil
'(lambda () (make-a-foo-1 :a
'what
)))
106 ;; should warn because B's default is NIL, not an integer.
107 (assert (and f warn err
)))
108 (multiple-value-bind (f warn err
)
109 (compile nil
'(lambda () (make-a-foo-2 3)))
110 ;; should warn because A's default is 0
111 (assert (and f warn err
)))))
113 (with-test (:name
:inline-structure-ctor-no-declaim
)
114 (let ((f (compile nil
116 (make-a-foo-1 :a
'wat
:b
3)))))
117 (assert (ctu:find-named-callees f
)))
118 (let ((f (compile nil
120 (declare (inline make-a-foo-1
))
121 (make-a-foo-1 :a
'wat
:b
3)))))
122 (assert (not (ctu:find-named-callees f
)))))
124 (with-test (:name
:internal-name-p
:skipped-on
:sb-xref-for-internals
)
125 (assert (sb-c::internal-name-p
'sb-int
:neq
)))
127 (with-test (:name
:coerce-callable-to-fun-note
)
128 (macrolet ((try (form what
)
130 (search ,(format nil
"~A is not known to be" what
)
131 (with-output-to-string (*error-output
*)
132 (compile nil
'(lambda (x)
133 (declare (optimize speed
))
134 (funcall ,form
))))))))
136 (try (eval `(work-with ,x
)) "callable expression")
138 ;; For this I'd accept either Z or X in the message.
139 (try (progn (let ((z x
)) (identity z
))) "X")))
141 (with-test (:name
:princ-to-string-unflushable
)
142 ;; Ordinary we'll flush it
143 (let ((f (compile nil
'(lambda (x) (princ-to-string x
) x
))))
144 (assert (not (ctu:find-named-callees f
:name
'princ-to-string
))))
145 ;; But in high safety it should be called for effect
146 (let ((f (compile nil
'(lambda (x)
147 (declare (optimize safety
)) (princ-to-string x
) x
))))
148 (assert (ctu:find-named-callees f
:name
'princ-to-string
))))
150 (with-test (:name
:map-allocated-objects-no-consing
151 :skipped-on
:sb-fasteval
154 (sb-int:dx-flet
((f (obj type size
)
155 (declare (ignore obj type size
))
157 (ctu:assert-no-consing
158 (sb-vm::map-allocated-objects
#'f
:dynamic
)
161 (with-test (:name
:pack-varints-as-bignum
)
162 (dotimes (i 500) ; do some random testing this many times
163 (let* ((random-numbers (loop repeat
(+ (random 20) 3)
164 collect
(1+ (random 4000))))
165 (test-list (sort (delete-duplicates random-numbers
) #'<))
166 (packed-int (sb-c::pack-code-fixup-locs test-list
))
167 (result (make-array 1 :element-type
'sb-ext
:word
)))
168 ;; The packer intrinsically self-checks the packing
169 ;; so we don't need to assert anything about that.
170 (sb-sys:with-pinned-objects
(packed-int result
)
171 ;; Now exercise the C unpacker.
172 ;; This hack of allocating 4 longs is terrible, but whatever.
173 (let ((unpacker (make-alien long
4))
175 (alien-funcall (extern-alien "varint_unpacker_init"
176 (function void
(* long
) unsigned
))
178 (sb-kernel:get-lisp-obj-address packed-int
))
179 (sb-int:collect
((unpacked))
183 (extern-alien "varint_unpack"
184 (function int
(* long
) system-area-pointer
))
185 unpacker
(sb-sys:vector-sap result
))))
186 (let ((val (aref result
0)))
187 ;; status of 0 is EOF, val = 0 means a decoded value was 0,
188 ;; which can't happen, so it's effectively EOF.
189 (when (or (eql status
0) (eql val
0)) (return))
190 (let ((loc (+ prev-loc val
)))
192 (setq prev-loc loc
)))))
193 (assert (equal (unpacked) test-list
))))))))