# 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.
. ./expect.sh
-base_tmpfilename="compiler-test-$$-tmp"
-tmpfilename="$base_tmpfilename.lisp"
-compiled_tmpfilename="$base_tmpfilename.fasl"
+use_test_subdirectory
+
+tmpfilename="$TEST_FILESTEM.lisp"
# This should fail, as type inference should show that the call to FOO
# will return something of the wrong type.
EOF
expect_failed_compile $tmpfilename
+# This should fail, as type inference should show that the call to FOO
+# has a wrong number of args.
+cat > $tmpfilename <<EOF
+ (in-package :cl-user)
+ (defun foo (x) (or x (foo x x)))
+EOF
+expect_failed_compile $tmpfilename
+
# This should fail, as we define a function multiply in the same file
# (CLHS 3.2.2.3).
cat > $tmpfilename <<EOF
# having the same name.
cat > $tmpfilename <<EOF
(in-package :cl-user)
- (defun foo (x)
+ (defun foo (x)
(flet ((baz (y) (load y)))
(declare (notinline baz))
(baz x)))
- (defun bar (x)
+ (defun bar (x)
(flet ((baz (y) (load y)))
(declare (notinline baz))
(baz x)))
cat > $tmpfilename <<EOF
(in-package :cl-user)
(defun foo (x) (list x))
- (defun bar (x)
+ (defun bar (x)
(declare (notinline foo))
(1+ (foo x)))
EOF
(defun foo (x)
(error x))
EOF
-fail_on_compiler_note $tmpfilename
+fail_on_condition_during_compile sb-ext:compiler-note $tmpfilename
# test case from Rudi for some CLOS WARNINGness that shouldn't have
# been there
cat > $tmpfilename <<EOF
+ #+sb-eval (eval-when (:compile-toplevel)
+ (setf sb-ext:*evaluator-mode* :compile))
+
(eval-when (:compile-toplevel :load-toplevel :execute)
- (defstruct buffer-state
+ (defstruct buffer-state
(output-index 0)))
-
+
(defclass buffered-stream-mixin ()
((buffer-state :initform (make-buffer-state))))
-
+
(defgeneric frob (stream))
(defmethod frob ((stream t))
nil)
(declare (muffle-conditions code-deletion-note))
(if t (foo) (foo)))
EOF
-fail_on_compiler_note $tmpfilename
+fail_on_condition_during_compile sb-ext:compiler-note $tmpfilename
cat > $tmpfilename <<EOF
(defun foo (x y)
(declare (optimize speed))
(+ x y))
EOF
-fail_on_compiler_note $tmpfilename
+fail_on_condition_during_compile sb-ext:compiler-note $tmpfilename
cat > $tmpfilename <<EOF
(declaim (muffle-conditions compiler-note))
(declare (optimize speed))
(+ x y))
EOF
-fail_on_compiler_note $tmpfilename
+fail_on_condition_during_compile sb-ext:compiler-note $tmpfilename
cat > $tmpfilename <<EOF
(declaim (muffle-conditions compiler-note))
(declare (optimize speed))
(+ x y))
EOF
-expect_compiler_note $tmpfilename
+expect_condition_during_compile sb-ext:compiler-note $tmpfilename
# undefined variable causes a WARNING
cat > $tmpfilename <<EOF
EOF
expect_failed_compile $tmpfilename
+# This should be clean
+cat > $tmpfilename <<EOF
+(defvar *string* (make-string 10 :element-type 'base-char))
+EOF
+expect_clean_compile $tmpfilename
+
# This should style-warn (but not warn or otherwise fail) as the call
# to FORMAT has too many arguments, which is bad style but not
# otherwise fatal.
EOF
expect_warned_compile $tmpfilename
-rm $tmpfilename
-rm $compiled_tmpfilename
+# Tests that destructive-functions on known-constant data cause
+# compile-time warnings.
+cat > $tmpfilename <<EOF
+(let ((string "foo"))
+ (defun foo ()
+ (setf string "bar")))
+EOF
+expect_clean_compile $tmpfilename
+
+cat > $tmpfilename <<EOF
+(defun foo ()
+ (let (result)
+ (nreverse result)))
+EOF
+expect_clean_compile $tmpfilename
+
+cat > $tmpfilename <<EOF
+(defun bar ()
+ (let ((result ""))
+ (nreverse result)))
+EOF
+expect_clean_compile $tmpfilename
+
+cat > $tmpfilename <<EOF
+(let ((string "foo"))
+ (defun foo ()
+ (replace string "bar")))
+EOF
+expect_failed_compile $tmpfilename
+
+cat > $tmpfilename <<EOF
+(defun foo ()
+ (setf (char "bar" 0) #\1))
+EOF
+expect_failed_compile $tmpfilename
+
+cat > $tmpfilename <<EOF
+(let ((foo '(1 2 3)))
+ (defun foo ()
+ (nconc foo foo)))
+EOF
+expect_failed_compile $tmpfilename
+
+cat > $tmpfilename <<EOF
+x
+y
+z
+EOF
+expect_failed_compile $tmpfilename
+
+cat > $tmpfilename <<EOF
+(declaim (optimize (speed 3) (space 0) (safety 0)))
+
+(defun foo (bar)
+ (last bar))
+EOF
+expect_clean_compile $tmpfilename
+
+cat > $tmpfilename <<EOF
+(defstruct foo
+ (bar #p"/tmp/"))
+EOF
+expect_clean_compile $tmpfilename
+
+cat > $tmpfilename <<EOF
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (defstruct foox)
+ (defmethod make-load-form ((foo foox) &optional env)
+ (declare (ignore env))
+ '(make-foox)))
+(defstruct bar
+ (foo #.(make-foox)))
+EOF
+expect_clean_compile $tmpfilename
+
+cat > $tmpfilename <<EOF
+(defun something (x) x)
+...
+(defun something-more (x) x)
+EOF
+expect_aborted_compile $tmpfilename
+
+cat > $tmpfilename <<EOF
+(if t (locally))
+EOF
+expect_clean_cload $tmpfilename
+
+cat > $tmpfilename <<EOF
+(defconstant cl-package (find-package :cl))
+(defun cl-symbol-p (x)
+ (eq (symbol-package x) cl-package))
+EOF
+expect_clean_cload $tmpfilename
+
+cat > $tmpfilename <<EOF
+(and (eval-when (:compile-toplevel) (error "oops AND")))
+(or (eval-when (:compile-toplevel) (error "oops OR")))
+(cond (t (eval-when (:compile-toplevel) (error "oops COND"))))
+EOF
+expect_clean_cload $tmpfilename
+
+# Test correct fasl-dumping of literals in arglist defaulting.
+# (LP Bug #310132)
+cat > $tmpfilename <<EOF
+(in-package :cl-user)
+
+;; These are CLHS examples from the dictionary entry for MAKE-LOAD-FORM.
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (defstruct my-struct a b c)
+ (defmethod make-load-form ((s my-struct) &optional environment)
+ (make-load-form-saving-slots s :environment environment))
+ (defclass my-class ()
+ ((x :initarg :x :reader obj-x)
+ (y :initarg :y :reader obj-y)
+ (dist :accessor obj-dist)))
+ (defmethod make-load-form ((self my-class) &optional environment)
+ (make-load-form-saving-slots self
+ :slot-names '(x y)
+ :environment environment)))
+
+(defun bar1 (&optional (x #.(make-my-struct)))
+ x)
+
+(defun bar2 (&optional (x #.(make-instance 'my-class)))
+ x)
+
+;; Packages are externalizable.
+(defun bar3 (&optional (x #.*package*))
+ x)
+
+(assert (typep (bar1) 'my-struct))
+(assert (typep (bar2) 'my-class))
+(assert (eq (bar3) *package*))
+
+EOF
+expect_clean_cload $tmpfilename
+
+cat > $tmpfilename <<EOF
+(in-package :cl-user)
+(defmacro foo () (error "ERROR at macroexpansion time."))
+(defun bar () (foo))
+EOF
+expect_condition_during_compile sb-c:compiler-error $tmpfilename
+
+cat > $tmpfilename <<EOF
+(eval-when (:compile-toplevel)
+ (error "ERROR within EVAL-WHEN."))
+EOF
+expect_condition_during_compile simple-error $tmpfilename
+
+cat > $tmpfilename <<EOF
+(defun slot-name-incf (s)
+ (with-slots (no-such-slot) s
+ (incf no-such-slot)))
+EOF
+expect_clean_cload $tmpfilename
+
+cat > $tmpfilename <<EOF
+(in-package :cl-user)
+
+(defun foo ()
+ (declare (muffle-conditions warning))
+ (let ((em 0d0))
+ (declare (type double-float em))
+ (dotimes (i 42)
+ (setf em (float (1+ i))))))
+EOF
+expect_clean_compile $tmpfilename
+
+cat > $tmpfilename <<EOF
+(in-package :cl-user)
+
+(defun foo ()
+ (declare (muffle-conditions warning))
+ (flet ((foo ()
+ (declare (values fixnum))
+ nil))
+ (foo)))
+EOF
+expect_clean_compile $tmpfilename
+
+cat > $tmpfilename <<EOF
+(in-package :cl-user)
+
+(defun foo (x)
+ (declare (muffle-conditions warning)
+ (type (vector (mod 7) 1) x))
+ (setf (aref x 0) 8)
+ x)
+EOF
+expect_clean_compile $tmpfilename
+
+cat > $tmpfilename <<EOF
+(in-package :cl-user)
+
+(declaim (notinline foo))
+(let ((i 0)) (defun foo (x) (incf i x)))
+(defun bar (x) (foo x))
+EOF
+fail_on_condition_during_compile sb-ext:compiler-note $tmpfilename
-# success
-exit 104
+# success
+exit $EXIT_TEST_WIN