1.0.17.4: support for dynamic-extent structures
[sbcl.git] / tests / compiler.impure.lisp
index 0f6da5e..8e78f57 100644 (file)
@@ -15,6 +15,9 @@
 ;;;; absolutely no warranty. See the COPYING and CREDITS files for
 ;;;; more information.
 
+(when (eq sb-ext:*evaluator-mode* :interpret)
+  (sb-ext:quit :unix-status 104))
+
 (load "test-util.lisp")
 (load "assertoid.lisp")
 (use-package "TEST-UTIL")
                               (declare (inline test-cmacro-4))
                               (test-cmacro-4)))))
 
+;;; SETF function compiler macros
+(define-compiler-macro (setf test-cmacro-4) (&whole form value) ''ok)
+
+(assert (eq 'ok (funcall (lambda () (setf (test-cmacro-4) 'zot)))))
+(assert (eq 'ok (funcall (lambda () (funcall #'(setf test-cmacro-4) 'zot)))))
+
+;;; Step instrumentation breaking type-inference
+(handler-bind ((warning #'error))
+  (assert (= 42 (funcall (compile nil '(lambda (v x)
+                                        (declare (optimize sb-c:insert-step-conditions))
+                                        (if (typep (the function x) 'fixnum)
+                                            (svref v (the function x))
+                                            (funcall x))))
+                         nil (constantly 42)))))
+
+;;; bug 368: array type intersections in the compiler
+(defstruct e368)
+(defstruct i368)
+(defstruct g368
+  (i368s (make-array 0 :fill-pointer t) :type (or (vector i368) null)))
+(defstruct s368
+  (g368 (error "missing :G368") :type g368 :read-only t))
+(declaim (ftype (function (fixnum (vector i368) e368) t) r368))
+(declaim (ftype (function (fixnum (vector e368)) t) h368))
+(defparameter *h368-was-called-p* nil)
+(defun nsu (vertices e368)
+  (let ((i368s (g368-i368s (make-g368))))
+    (let ((fuis (r368 0 i368s e368)))
+      (format t "~&FUIS=~S~%" fuis)
+      (or fuis (h368 0 i368s)))))
+(defun r368 (w x y)
+  (declare (ignore w x y))
+  nil)
+(defun h368 (w x)
+  (declare (ignore w x))
+  (setf *h368-was-called-p* t)
+  (make-s368 :g368 (make-g368)))
+(let ((nsu (nsu #() (make-e368))))
+  (format t "~&NSU returned ~S~%" nsu)
+  (format t "~&*H368-WAS-CALLED-P*=~S~%" *h368-was-called-p*)
+  (assert (s368-p nsu))
+  (assert *h368-was-called-p*))
+
+;;; bug 367: array type intersections in the compiler
+(defstruct e367)
+(defstruct i367)
+(defstruct g367
+  (i367s (make-array 0 :fill-pointer t) :type (or (vector i367) null)))
+(defstruct s367
+  (g367 (error "missing :G367") :type g367 :read-only t))
+(declaim (ftype (function ((vector i367) e367) (or s367 null)) r367))
+(declaim (ftype (function ((vector e367)) (values)) h367))
+(defun frob-367 (v w)
+  (let ((x (g367-i367s (make-g367))))
+    (let* ((y (or (r367 x w)
+                  (h367 x)))
+           (z (s367-g367 y)))
+      (format t "~&Y=~S Z=~S~%" y z)
+      (g367-i367s z))))
+(defun r367 (x y) (declare (ignore x y)) nil)
+(defun h367 (x) (declare (ignore x)) (values))
+(multiple-value-bind (res err) (ignore-errors (frob-367 0 (make-e367)))
+  (assert (not res))
+  (assert (typep err 'type-error)))
+
+(handler-case
+    (delete-file (compile-file "circ-tree-test.lisp"))
+  (storage-condition (e)
+    (error e)))
+
+;;; warnings due to step-insturmentation
+(defclass debug-test-class () ())
+(handler-case
+    (compile nil '(lambda ()
+                   (declare (optimize (debug 3)))
+                   (defmethod print-object ((x debug-test-class) s)
+                     (call-next-method))))
+  ((and (not style-warning) warning) (e)
+    (error e)))
+
+;;; program-error from bad lambda-list keyword
+(assert (eq :ok
+            (handler-case
+                (funcall (lambda (&whole x)
+                           (list &whole x)))
+              (program-error ()
+                :ok))))
+(assert (eq :ok
+            (handler-case
+                (let ((*evaluator-mode* :interpret))
+                  (funcall (eval '(lambda (&whole x)
+                                   (list &whole x)))))
+              (program-error ()
+                :ok))))
+
+;;; ignore &environment
+(handler-bind ((style-warning #'error))
+  (compile nil '(lambda ()
+                 (defmacro macro-ignore-env (&environment env)
+                   (declare (ignore env))
+                   :foo)))
+  (compile nil '(lambda ()
+                 (defmacro macro-no-env ()
+                   :foo))))
+
+(dolist (*evaluator-mode* '(:interpret :compile))
+  (disassemble (eval '(defun disassemble-source-form-bug (x y z)
+                       (declare (optimize debug))
+                       (list x y z)))))
+
+;;; long-standing bug in defaulting unknown values on the x86-64,
+;;; since changing the calling convention (test case by Christopher
+;;; Laux sbcl-help 30-06-2007)
+
+(defun default-values-bug-demo-sub ()
+  (format t "test")
+  nil)
+(compile 'default-values-bug-demo-sub)
+
+(defun default-values-bug-demo-main ()
+  (multiple-value-bind (a b c d e f g h)
+      (default-values-bug-demo-sub)
+    (if a (+ a b c d e f g h) t)))
+(compile 'default-values-bug-demo-main)
+
+(assert (default-values-bug-demo-main))
+
+;;; copy propagation bug reported by Paul Khuong
+
+(defun local-copy-prop-bug-with-move-arg (x)
+  (labels ((inner ()
+             (values 1 0)))
+    (if x
+        (inner)
+        (multiple-value-bind (a b)
+            (inner)
+          (values b a)))))
+
+(assert (equal '(0 1) (multiple-value-list (local-copy-prop-bug-with-move-arg nil))))
+(assert (equal '(1 0) (multiple-value-list (local-copy-prop-bug-with-move-arg t))))
+
+;;;; with-pinned-objects & unwind-protect, using all non-tail conventions
+
+(defun wpo-quux () (list 1 2 3))
+(defvar *wpo-quux* #'wpo-quux)
+
+(defun wpo-call ()
+  (unwind-protect
+       (sb-sys:with-pinned-objects (*wpo-quux*)
+         (values (funcall *wpo-quux*)))))
+(assert (equal '(1 2 3) (wpo-call)))
+
+(defun wpo-multiple-call ()
+  (unwind-protect
+       (sb-sys:with-pinned-objects (*wpo-quux*)
+         (funcall *wpo-quux*))))
+(assert (equal '(1 2 3) (wpo-multiple-call)))
+
+(defun wpo-call-named ()
+  (unwind-protect
+       (sb-sys:with-pinned-objects (*wpo-quux*)
+         (values (wpo-quux)))))
+(assert (equal '(1 2 3) (wpo-call-named)))
+
+(defun wpo-multiple-call-named ()
+  (unwind-protect
+       (sb-sys:with-pinned-objects (*wpo-quux*)
+         (wpo-quux))))
+(assert (equal '(1 2 3) (wpo-multiple-call-named)))
+
+(defun wpo-call-variable (&rest args)
+  (unwind-protect
+       (sb-sys:with-pinned-objects (*wpo-quux*)
+         (values (apply *wpo-quux* args)))))
+(assert (equal '(1 2 3) (wpo-call-variable)))
+
+(defun wpo-multiple-call-variable (&rest args)
+  (unwind-protect
+       (sb-sys:with-pinned-objects (*wpo-quux*)
+         (apply #'wpo-quux args))))
+(assert (equal '(1 2 3) (wpo-multiple-call-named)))
+
+(defun wpo-multiple-call-local ()
+  (flet ((quux ()
+           (wpo-quux)))
+    (unwind-protect
+         (sb-sys:with-pinned-objects (*wpo-quux*)
+           (quux)))))
+(assert (equal '(1 2 3) (wpo-multiple-call-local)))
+
+;;; bug 417: toplevel NIL confusing source path logic
+(handler-case
+    (delete-file (compile-file "bug-417.lisp"))
+  (sb-ext:code-deletion-note (e)
+    (error e)))
+
+;;; unknown values return convention getting disproportionate
+;;; amounts of values.
+(declaim (notinline one-value two-values))
+(defun one-value (x)
+  (not x))
+(defun two-values (x y)
+  (values y x))
+(defun wants-many-values (x y)
+  (multiple-value-bind (a b c d e f)
+      (one-value y)
+    (assert (and (eql (not y) a)
+                 (not (or b c d e f)))))
+  (multiple-value-bind (a b c d e f)
+      (two-values y x)
+    (assert (and (eql a x) (eql b y)
+                 (not (or c d e f)))))
+  (multiple-value-bind (a b c d e f g h i)
+      (one-value y)
+    (assert (and (eql (not y) a)
+                 (not (or b c d e f g h i)))))
+  (multiple-value-bind (a b c d e f g h i)
+      (two-values y x)
+    (assert (and (eql a x) (eql b y)
+                 (not (or c d e f g h i)))))
+  (multiple-value-bind (a b c d e f g h i j k l m n o p q r s)
+      (one-value y)
+    (assert (and (eql (not y) a)
+                 (not (or b c d e f g h i j k l m n o p q r s)))))
+  (multiple-value-bind (a b c d e f g h i j k l m n o p q r s)
+      (two-values y x)
+    (assert (and (eql a x) (eql b y)
+                 (not (or c d e f g h i j k l m n o p q r s))))))
+(wants-many-values 1 42)
+
+;;; constant coalescing (named and unnamed)
+(defconstant +born-to-coalesce+ '.born-to-coalesce.)
+(let* ((f (compile nil '(lambda ()
+                         (let ((x (cons +born-to-coalesce+ nil))
+                               (y (cons '.born-to-coalesce. nil)))
+                           (list x y)))))
+       (b-t-c 0)
+       (code (sb-kernel:fun-code-header f)))
+  (loop for i from sb-vm::code-constants-offset below (sb-kernel:get-header-data code)
+        do (when (eq '.born-to-coalesce. (sb-kernel:code-header-ref code i))
+             (incf b-t-c)))
+  (assert (= 1 b-t-c)))
+
 ;;; success