1.0.28.38: undefined warning and compilation unit summary tweaking
[sbcl.git] / tests / compiler.pure.lisp
index b261254..08fbf6a 100644 (file)
 ;;;; absolutely no warranty. See the COPYING and CREDITS files for
 ;;;; more information.
 
+(cl:in-package :sb-c)
+
+(defknown compiler-derived-type (t) (values t t) (movable flushable unsafe))
+
+(deftransform compiler-derived-type ((x))
+ `(values ',(type-specifier (lvar-type x)) t))
+
+(defun compiler-derived-type (x)
+  (values t nil))
+
 (cl:in-package :cl-user)
 
 ;; The tests in this file assume that EVAL will use the compiler
               (+ 81535869 (the (member 17549.955 #:g35917) p2))))
            17549.955)
           (+ 81535869 17549.955)))
+
+;;; misc.654
+(assert (eql 2
+             (let ((form '(lambda (p2)
+                           (declare (optimize (speed 0) (safety 2) (debug 0) (space 2))
+                            (type (member integer eql) p2))
+                           (coerce 2 p2))))
+               (funcall (compile nil form) 'integer))))
+
+;;; misc.656
+(assert (eql 2
+             (let ((form '(lambda (p2)
+                           (declare (optimize (speed 0) (safety 2) (debug 0) (space 2))
+                            (type (member integer mod) p2))
+                           (coerce 2 p2))))
+               (funcall (compile nil form) 'integer))))
+
+;;; misc.657
+(assert (eql 2
+         (let ((form '(lambda (p2)
+                       (declare (optimize (speed 0) (safety 2) (debug 0) (space 2))
+                        (type (member integer values) p2))
+                       (coerce 2 p2))))
+           (funcall (compile nil form) 'integer))))
+
+(with-test (:name :string-aref-type)
+ (assert (eq 'character
+             (funcall (compile nil
+                               '(lambda (s)
+                                 (sb-c::compiler-derived-type (aref (the string s) 0))))
+                      "foo"))))
+
+(with-test (:name :base-string-aref-type)
+ (assert (eq #+sb-unicode 'base-char
+             #-sb-unicode 'character
+             (funcall (compile nil
+                               '(lambda (s)
+                                 (sb-c::compiler-derived-type (aref (the base-string s) 0))))
+                      (coerce "foo" 'base-string)))))
+
+(with-test (:name :dolist-constant-type-derivation)
+  (assert (equal '(integer 1 3)
+                 (funcall (compile nil
+                                   '(lambda (x)
+                                     (dolist (y '(1 2 3))
+                                       (when x
+                                         (return (sb-c::compiler-derived-type y))))))
+                          t))))
+
+(with-test (:name :dolist-simple-list-type-derivation)
+  (assert (equal '(integer 1 3)
+                 (funcall (compile nil
+                                   '(lambda (x)
+                                     (dolist (y (list 1 2 3))
+                                       (when x
+                                         (return (sb-c::compiler-derived-type y))))))
+                          t))))
+
+(with-test (:name :dolist-dotted-constant-list-type-derivation)
+  (let* ((warned nil)
+         (fun (handler-bind ((style-warning (lambda (c) (push c warned))))
+                (compile nil
+                         '(lambda (x)
+                           (dolist (y '(1 2 3 . 4) :foo)
+                             (when x
+                               (return (sb-c::compiler-derived-type y)))))))))
+    (assert (equal '(integer 1 3) (funcall fun t)))
+    (assert (= 1 (length warned)))
+    (multiple-value-bind (res err) (ignore-errors (funcall fun nil))
+      (assert (not res))
+      (assert (typep err 'type-error)))))
+
+(with-test (:name :constant-list-destructuring)
+  (handler-bind ((sb-ext:compiler-note #'error))
+    (progn
+      (assert (= 10
+                 (funcall
+                  (compile nil
+                           '(lambda ()
+                             (destructuring-bind (a (b c) d) '(1 (2 3) 4)
+                               (+ a b c d)))))))
+      (assert (eq :feh
+                  (funcall
+                   (compile nil
+                            '(lambda (x)
+                              (or x
+                               (destructuring-bind (a (b c) d) '(1 "foo" 4)
+                                 (+ a b c d)))))
+                   :feh))))))
+
+;;; Functions with non-required arguments used to end up with
+;;; (&OPTIONAL-DISPATCH ...) as their names.
+(with-test (:name :hairy-function-name)
+  (assert (eq 'read-line (nth-value 2 (function-lambda-expression #'read-line))))
+  (assert (equal "#<FUNCTION READ-LINE>" (princ-to-string #'read-line))))
+
+;;; PROGV + RESTRICT-COMPILER-POLICY
+(with-test (:name :progv-and-restrict-compiler-policy)
+  (let ((sb-c::*policy-restrictions* sb-c::*policy-restrictions*))
+    (restrict-compiler-policy 'debug 3)
+    (let ((fun (compile nil '(lambda (x)
+                              (let ((i x))
+                                (declare (special i))
+                                (list i
+                                      (progv '(i) (list (+ i 1))
+                                        i)
+                                      i))))))
+      (assert (equal '(1 2 1) (funcall fun 1))))))
+
+;;; It used to be possible to confuse the compiler into
+;;; IR2-converting such a call to CONS
+(with-test (:name :late-bound-primitive)
+  (compile nil `(lambda ()
+                  (funcall 'cons 1))))
+
+(with-test (:name :hairy-array-element-type-derivation)
+  (compile nil '(lambda (x)
+                 (declare (type (and simple-string (satisfies array-has-fill-pointer-p)) x))
+                 (array-element-type x))))
+
+(with-test (:name :rest-list-type-derivation)
+  (multiple-value-bind (type derivedp)
+      (funcall (compile nil `(lambda (&rest args)
+                               (sb-c::compiler-derived-type args)))
+               nil)
+    (assert (eq 'list type))
+    (assert derivedp)))
+
+(with-test (:name :base-char-typep-elimination)
+  (assert (eq (funcall (lambda (ch)
+                         (declare (type base-char ch) (optimize (speed 3) (safety 0)))
+                         (typep ch 'base-char))
+                       t)
+              t)))
+
+(with-test (:name :regression-1.0.24.37)
+  (compile nil '(lambda (&key (test (constantly t)))
+                 (when (funcall test)
+                   :quux))))
+
+;;; Attempt to test a decent cross section of conditions
+;;; and values types to move conditionally.
+(macrolet
+    ((test-comparison (comparator type x y)
+       `(progn
+          ,@(loop for (result-type a b)
+                    in '((nil t   nil)
+                         (nil 0   1)
+                         (nil 0.0 1.0)
+                         (nil 0d0 0d0)
+                         (nil 0.0 0d0)
+                         (nil #c(1.0 1.0) #c(2.0 2.0))
+
+                         (t      t  nil)
+                         (fixnum 0 1)
+                         ((unsigned-byte #.sb-vm:n-word-bits)
+                          (1+ most-positive-fixnum)
+                          (+ 2 most-positive-fixnum))
+                         ((signed-byte #.sb-vm:n-word-bits)
+                          -1 (* 2 most-negative-fixnum))
+                         (single-float 0.0 1.0)
+                         (double-float 0d0 1d0))
+                  for lambda = (if result-type
+                                   `(lambda (x y a b)
+                                      (declare (,type x y)
+                                               (,result-type a b))
+                                      (if (,comparator x y)
+                                          a b))
+                                   `(lambda (x y)
+                                      (declare (,type x y))
+                                      (if (,comparator x y)
+                                          ,a ,b)))
+                  for args = `(,x ,y ,@(and result-type
+                                            `(,a ,b)))
+                  collect
+                  `(progn
+                     (eql (funcall (compile nil ',lambda)
+                                   ,@args)
+                          (eval '(,lambda ,@args))))))))
+  (sb-vm::with-float-traps-masked
+      (:divide-by-zero :overflow :inexact :invalid)
+    (let ((sb-ext:*evaluator-mode* :interpret))
+      (declare (sb-ext:muffle-conditions style-warning))
+      (test-comparison eql t t nil)
+      (test-comparison eql t t t)
+
+      (test-comparison =   t 1 0)
+      (test-comparison =   t 1 1)
+      (test-comparison =   t (1+ most-positive-fixnum) (+ 2 most-positive-fixnum))
+      (test-comparison =   fixnum 1 0)
+      (test-comparison =   fixnum 0 0)
+      (test-comparison =   (unsigned-byte #.sb-vm:n-word-bits) 1 0)
+      (test-comparison =   (unsigned-byte #.sb-vm:n-word-bits) 0 0)
+      (test-comparison =   (signed-byte #.sb-vm:n-word-bits)   1 0)
+      (test-comparison =   (signed-byte #.sb-vm:n-word-bits)   1 1)
+
+      (test-comparison =   single-float 0.0 1.0)
+      (test-comparison =   single-float 1.0 1.0)
+      (test-comparison =   single-float (/ 1.0 0.0) (/ 1.0 0.0))
+      (test-comparison =   single-float (/ 1.0 0.0) 1.0)
+      (test-comparison =   single-float (/ 0.0 0.0) (/ 0.0 0.0))
+      (test-comparison =   single-float (/ 0.0 0.0) 0.0)
+
+      (test-comparison =   double-float 0d0 1d0)
+      (test-comparison =   double-float 1d0 1d0)
+      (test-comparison =   double-float (/ 1d0 0d0) (/ 1d0 0d0))
+      (test-comparison =   double-float (/ 1d0 0d0) 1d0)
+      (test-comparison =   double-float (/ 0d0 0d0) (/ 0d0 0d0))
+      (test-comparison =   double-float (/ 0d0 0d0) 0d0)
+
+      (test-comparison <   t 1 0)
+      (test-comparison <   t 0 1)
+      (test-comparison <   t 1 1)
+      (test-comparison <   t (1+ most-positive-fixnum)  (+ 2 most-positive-fixnum))
+      (test-comparison <   t (+ 2 most-positive-fixnum) (1+ most-positive-fixnum))
+      (test-comparison <   fixnum 1 0)
+      (test-comparison <   fixnum 0 1)
+      (test-comparison <   fixnum 0 0)
+      (test-comparison <   (unsigned-byte #.sb-vm:n-word-bits) 1 0)
+      (test-comparison <   (unsigned-byte #.sb-vm:n-word-bits) 0 1)
+      (test-comparison <   (unsigned-byte #.sb-vm:n-word-bits) 0 0)
+      (test-comparison <   (signed-byte #.sb-vm:n-word-bits)   1 0)
+      (test-comparison <   (signed-byte #.sb-vm:n-word-bits)   0 1)
+      (test-comparison <   (signed-byte #.sb-vm:n-word-bits)   1 1)
+
+      (test-comparison <   single-float 0.0 1.0)
+      (test-comparison <   single-float 1.0 0.0)
+      (test-comparison <   single-float 1.0 1.0)
+      (test-comparison <   single-float (/ 1.0 0.0) (/ 1.0 0.0))
+      (test-comparison <   single-float (/ 1.0 0.0) 1.0)
+      (test-comparison <   single-float 1.0 (/ 1.0 0.0))
+      (test-comparison <   single-float (/ 0.0 0.0) (/ 0.0 0.0))
+      (test-comparison <   single-float (/ 0.0 0.0) 0.0)
+
+      (test-comparison <   double-float 0d0 1d0)
+      (test-comparison <   double-float 1d0 0d0)
+      (test-comparison <   double-float 1d0 1d0)
+      (test-comparison <   double-float (/ 1d0 0d0) (/ 1d0 0d0))
+      (test-comparison <   double-float (/ 1d0 0d0) 1d0)
+      (test-comparison <   double-float 1d0 (/ 1d0 0d0))
+      (test-comparison <   double-float (/ 0d0 0d0) (/ 0d0 0d0))
+      (test-comparison <   double-float (/ 0d0 0d0) 0d0)
+      (test-comparison <   double-float 0d0 (/ 0d0 0d0))
+
+      (test-comparison >   t 1 0)
+      (test-comparison >   t 0 1)
+      (test-comparison >   t 1 1)
+      (test-comparison >   t (1+ most-positive-fixnum)  (+ 2 most-positive-fixnum))
+      (test-comparison >   t (+ 2 most-positive-fixnum) (1+ most-positive-fixnum))
+      (test-comparison >   fixnum 1 0)
+      (test-comparison >   fixnum 0 1)
+      (test-comparison >   fixnum 0 0)
+      (test-comparison >   (unsigned-byte #.sb-vm:n-word-bits) 1 0)
+      (test-comparison >   (unsigned-byte #.sb-vm:n-word-bits) 0 1)
+      (test-comparison >   (unsigned-byte #.sb-vm:n-word-bits) 0 0)
+      (test-comparison >   (signed-byte #.sb-vm:n-word-bits)   1 0)
+      (test-comparison >   (signed-byte #.sb-vm:n-word-bits)   0 1)
+      (test-comparison >   (signed-byte #.sb-vm:n-word-bits)   1 1)
+
+      (test-comparison >   single-float 0.0 1.0)
+      (test-comparison >   single-float 1.0 0.0)
+      (test-comparison >   single-float 1.0 1.0)
+      (test-comparison >   single-float (/ 1.0 0.0) (/ 1.0 0.0))
+      (test-comparison >   single-float (/ 1.0 0.0) 1.0)
+      (test-comparison >   single-float 1.0 (/ 1.0 0.0))
+      (test-comparison >   single-float (/ 0.0 0.0) (/ 0.0 0.0))
+      (test-comparison >   single-float (/ 0.0 0.0) 0.0)
+
+      (test-comparison >   double-float 0d0 1d0)
+      (test-comparison >   double-float 1d0 0d0)
+      (test-comparison >   double-float 1d0 1d0)
+      (test-comparison >   double-float (/ 1d0 0d0) (/ 1d0 0d0))
+      (test-comparison >   double-float (/ 1d0 0d0) 1d0)
+      (test-comparison >   double-float 1d0 (/ 1d0 0d0))
+      (test-comparison >   double-float (/ 0d0 0d0) (/ 0d0 0d0))
+      (test-comparison >   double-float (/ 0d0 0d0) 0d0)
+      (test-comparison >   double-float 0d0 (/ 0d0 0d0)))))
+
+(with-test (:name :car-and-cdr-type-derivation-conservative)
+  (let ((f1 (compile nil
+                     `(lambda (y)
+                        (declare (optimize speed))
+                        (let ((x (the (cons fixnum fixnum) (cons 1 2))))
+                          (declare (type (cons t fixnum) x))
+                          (rplaca x y)
+                          (+ (car x) (cdr x))))))
+        (f2 (compile nil
+                     `(lambda (y)
+                        (declare (optimize speed))
+                        (let ((x (the (cons fixnum fixnum) (cons 1 2))))
+                          (setf (cdr x) y)
+                          (+ (car x) (cdr x)))))))
+    (flet ((test-error (e value)
+             (assert (typep e 'type-error))
+             (assert (eq 'number (type-error-expected-type e)))
+             (assert (eq value (type-error-datum e)))))
+      (let ((v1 "foo")
+            (v2 "bar"))
+        (multiple-value-bind (res err) (ignore-errors (funcall f1 v1))
+          (assert (not res))
+          (test-error err v1))
+        (multiple-value-bind (res err) (ignore-errors (funcall f2 v2))
+          (assert (not res))
+          (test-error err v2))))))
+
+(with-test (:name :array-dimension-derivation-conservative)
+  (let ((f (compile nil
+                    `(lambda (x)
+                       (declare (optimize speed))
+                       (declare (type (array * (4 4)) x))
+                       (let ((y x))
+                         (setq x (make-array '(4 4)))
+                         (adjust-array y '(3 5))
+                         (array-dimension y 0))))))
+    (assert (= 3 (funcall f (make-array '(4 4) :adjustable t))))))
+
+(with-test (:name :with-timeout-code-deletion-note)
+  (handler-bind ((sb-ext:code-deletion-note #'error))
+    (compile nil `(lambda ()
+                    (sb-ext:with-timeout 0
+                      (sleep 1))))))
+
+(with-test (:name :full-warning-for-undefined-type-in-cl)
+  (assert (eq :full
+              (handler-case
+                  (compile nil `(lambda (x) (the replace x)))
+                (style-warning ()
+                  :style)
+                (warning ()
+                  :full)))))
+
+(with-test (:name :single-warning-for-single-undefined-type)
+  (let ((n 0))
+    (handler-bind ((warning (lambda (c)
+                              (declare (ignore c))
+                              (incf n))))
+      (compile nil `(lambda (x) (the #:no-type x)))
+      (assert (= 1 n))
+      (compile nil `(lambda (x) (the 'fixnum x)))
+      (assert (= 2 n)))))