+;;; DEFINE-COMPILER-MACRO to work as expected, not via weird magical
+;;; IR1 pseudo-:COMPILE-TOPLEVEL handling
+(defvar *bug219-a-expanded-p* nil)
+(defun bug219-a (x)
+ (+ x 1))
+(define-compiler-macro bug219-a (&whole form y)
+ (setf *bug219-a-expanded-p* t)
+ (if (constantp y)
+ (+ (eval y) 2)
+ form))
+(defun bug219-a-aux ()
+ (bug219-a 2))
+(assert (= (bug219-a-aux)
+ (if *bug219-a-expanded-p* 4 3)))
+(defvar *bug219-a-temp* 3)
+(assert (= (bug219-a *bug219-a-temp*) 4))
+
+(defvar *bug219-b-expanded-p* nil)
+(defun bug219-b-aux1 (x)
+ (when x
+ (define-compiler-macro bug219-b (y)
+ (setf *bug219-b-expanded-p* t)
+ `(+ ,y 2))))
+(defun bug219-b-aux2 (z)
+ (bug219-b z))
+(assert (not *bug219-b-expanded-p*))
+(assert (raises-error? (bug219-b-aux2 1) undefined-function))
+(bug219-b-aux1 t)
+(defun bug219-b-aux2 (z)
+ (bug219-b z))
+(defun bug219-b (x)
+ x)
+(assert (= (bug219-b-aux2 1)
+ (if *bug219-b-expanded-p* 3 1)))
+
+;;; bug 224: failure in unreachable code deletion
+(defmacro do-optimizations (&body body)
+ `(dotimes (.speed. 4)
+ (dotimes (.space. 4)
+ (dotimes (.debug. 4)
+ (dotimes (.compilation-speed. 4)
+ (proclaim `(optimize (speed , .speed.) (space , .space.)
+ (debug , .debug.)
+ (compilation-speed , .compilation-speed.)))
+ ,@body)))))
+
+(do-optimizations
+ (compile nil
+ (read-from-string
+ "(lambda () (#:localy (declare (optimize (safety 3)))
+ (ignore-errors (progn (values-list (car (list '(1 . 2)))) t))))")))
+
+(do-optimizations
+ (compile nil '(lambda ()
+ (labels ((ext ()
+ (tagbody
+ (labels ((i1 () (list (i2) (i2)))
+ (i2 () (list (int) (i1)))
+ (int () (go :exit)))
+ (list (i1) (i1) (i1)))
+ :exit (return-from ext)
+ )))
+ (list (error "nih") (ext) (ext))))))
+
+(do-optimizations
+ (compile nil '(lambda (x) (let ((y (error ""))) (list x y)))))
+
+;;; bug 223: invalid moving of global function name referencing
+(defun bug223-int (n)
+ `(int ,n))
+
+(defun bug223-wrap ()
+ (let ((old #'bug223-int))
+ (setf (fdefinition 'bug223-int)
+ (lambda (n)
+ (assert (> n 0))
+ `(ext ,@(funcall old (1- n)))))))
+(compile 'bug223-wrap)
+
+(assert (equal (bug223-int 4) '(int 4)))
+(bug223-wrap)
+(assert (equal (bug223-int 4) '(ext int 3)))
+(bug223-wrap)
+(assert (equal (bug223-int 4) '(ext ext int 2)))
+\f
+;;; COERCE got its own DEFOPTIMIZER which has to reimplement most of
+;;; SPECIFIER-TYPE-NTH-ARG. For a while, an illegal type would throw
+;;; you into the debugger on compilation.
+(defun coerce-defopt (x)
+ ;; illegal, but should be compilable.
+ (coerce x '(values t)))
+(assert (null (ignore-errors (coerce-defopt 3))))
+\f
+;;; Oops. In part of the (CATCH ..) implementation of DEBUG-RETURN,
+;;; it was possible to confuse the type deriver of the compiler
+;;; sufficiently that compiler invariants were broken (explained by
+;;; APD sbcl-devel 2003-01-11).
+
+;;; WHN's original report
+(defun debug-return-catch-break1 ()
+ (with-open-file (s "/tmp/foo"
+ :direction :output
+ :element-type (list
+ 'signed-byte
+ (1+
+ (integer-length most-positive-fixnum))))
+ (read-byte s)
+ (read-byte s)
+ (read-byte s)
+ (read-byte s)))
+
+;;; APD's simplified test case
+(defun debug-return-catch-break2 (x)
+ (declare (type (vector (unsigned-byte 8)) x))
+ (setq *y* (the (unsigned-byte 8) (aref x 4))))
+\f
+;;; FUNCTION-LAMBDA-EXPRESSION should return something that's COMPILE
+;;; can understand. Here's a simple test for that on a function
+;;; that's likely to return a hairier list than just a lambda:
+(macrolet ((def (fn) `(progn
+ (declaim (inline ,fn))
+ (defun ,fn (x) (1+ x)))))
+ (def bug228))
+(let ((x (function-lambda-expression #'bug228)))
+ (when x
+ (assert (= (funcall (compile nil x) 1) 2))))
+
+;;; Bug reported by reported by rif on c.l.l 2003-03-05
+(defun test-type-of-special-1 (x)
+ (declare (special x)
+ (fixnum x)
+ (optimize (safety 3)))
+ (list x))
+(defun test-type-of-special-2 (x)
+ (declare (special x)
+ (fixnum x)
+ (optimize (safety 3)))
+ (list x (setq x (/ x 2)) x))
+(assert (raises-error? (test-type-of-special-1 3/2) type-error))
+(assert (raises-error? (test-type-of-special-2 3) type-error))
+(assert (equal (test-type-of-special-2 8) '(8 4 4)))
+