;;;; This software is part of the SBCL system. See the README file for ;;;; more information. ;;;; ;;;; While most of SBCL is derived from the CMU CL system, the test ;;;; files (like this one) were written from scratch after the fork ;;;; from CMU CL. ;;;; ;;;; This software is in the public domain and is provided with ;;;; absolutely no warranty. See the COPYING and CREDITS files for ;;;; more information. (cl:in-package :cl-user) ;;;; recognize self-calls (declaim (optimize speed)) ;;; This is a fopcompilable form that caused FOP stack underflow ;;; because the PROGN and SETQ each failed to push a NIL onto the stack. ;;; >>> DO NOT ADD A (WITH-TEST) TO THIS. <<< It must stay fopcompilable. (let ((a (progn)) ; lp# 1427050 (b (setq)) (c (+ 1 2))) (print c) (defvar *aaa* a) (defvar *bbb* b)) ;;;; These three forms should be equivalent. ;;; This used to be a bug in the handling of null-lexenv vs toplevel ;;; policy: LOCALLY and MACROLET hid the toplevel policy from view. (locally (defun foo (n) (frob 'foo) (if (<= n 0) n (foo (1- n))))) (progn (defun bar (n) (frob 'bar) (if (<= n 0) n (bar (1- n))))) (macrolet () (defun quux (n) (frob 'quux) (if (<= n 0) n (quux (1- n))))) (defun frob (x) (setf (fdefinition x) (constantly -11))) (defun test () (list (foo 1) (bar 1) (quux 1))) (assert (equal (test) '(0 0 0))) (assert (equal (test) '(-11 -11 -11))) ; sanity check ;;; Bug in 1.0.2 and 1.0.3, where the XEP was compiled with the wrong ;;; policy. (Test-case derived from code posted by alexander.ekart in ;;; comp.lang.lisp). (locally (declare (optimize (safety 0))) (defun bubblesort (x y) (declare (type (simple-array fixnum (*)) x) (type fixnum y) (optimize (speed 3) (safety 3) (space 0) (debug 0))) (aref x y))) (assert-error (bubblesort (eval '(make-array 10)) 9)) (define-symbol-macro %trash% what) (locally ;; just in case we get so smart that INFO becomes foldable (declare (notinline sb-int:info)) (assert (eq (sb-int:info :variable :kind '%trash%) :macro)) (assert (eq (sb-int:info :variable :macro-expansion '%trash%) 'what)) (assert (sb-int:info :source-location :symbol-macro '%trash%))) (let () (declare (notinline sb-int:info)) (defconstant %trash% 9) ; this is non-toplevel (multiple-value-bind (val foundp) (sb-int:info :variable :macro-expansion '%trash%) (assert (and (not val) (not foundp))))) ;; This must be one toplevel form. ;; In practice you'd never do anything like this I suspect. (progn (defvar *foofoo1* 1) (eval-when (:compile-toplevel) (setq sb-c::*source-plist* '(strange "Yes"))) (defvar *foofoo2* 2)) (with-test (:name :source-location-plist-invalid-memoization) (assert (null (sb-c:definition-source-location-plist (sb-int:info :source-location :variable '*foofoo1*)))) (assert (equal (sb-c:definition-source-location-plist (sb-int:info :source-location :variable '*foofoo2*)) '(strange "Yes")))) (defstruct zombie-cast-struct (value nil :type zombie-cast-struct-v)) (defstruct zombie-cast-struct-v (uses nil :type (or list zombie-cast-struct))) (with-test (:name :flush-zombie-casts) (checked-compile `(lambda (x) (declare (optimize (debug 2) (speed 1))) (let ((value (zombie-cast-struct-value x))) (labels ((l (x) (declare (ignore x)) (let ((uses (zombie-cast-struct-v-uses value))) (when (zombie-cast-struct-p uses) (list* uses (l uses))))))))))) (let () (define-condition non-top-level-condition (error) ())) (with-test (:name :non-top-level-condition) (assert (handler-case (signal 'non-top-level-condition) (non-top-level-condition () t)))) (defun somefun (x) (declare (optimize (sb-c:store-source-form 3))) (+ x 101)) (locally (declare (optimize (sb-c:store-source-form 3))) (defun otherfun (y) (/ y 3))) (locally (declare (optimize (sb-c:store-source-form 2))) (defun nosourcefun (y) (/ y 3))) (with-test (:name :store-source-form) (assert (function-lambda-expression #'somefun)) (assert (function-lambda-expression #'otherfun)) (assert (not (function-lambda-expression #'nosourcefun))))