0.8.17.10: stricter DEFCLASS option checking
authorNikodemus Siivola <nikodemus@random-state.net>
Wed, 1 Dec 2004 15:58:02 +0000 (15:58 +0000)
committerNikodemus Siivola <nikodemus@random-state.net>
Wed, 1 Dec 2004 15:58:02 +0000 (15:58 +0000)
            * as reported by Bruno Haible, an error should be
              signalled if a class-option appears multiple times.

NEWS
src/pcl/defclass.lisp
tests/mop.impure.lisp
version.lisp-expr

diff --git a/NEWS b/NEWS
index 3aabb52..ae049a1 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,9 @@ changes in sbcl-0.8.18 relative to sbcl-0.8.17:
     (backtraces from throws to unknown catch tags.)
   * bug fix: lambda-list parsing is now stricter vrt. order and number
     of lambda-list keywords.
+  * bug fix: as specified by AMOP, an error is signalled if a
+    class-option appears multiple times in a DEFCLASS form. (reported
+    by Bruno Haible)
   * fixed some bugs revealed by Paul Dietz' test suite:
     ** INCF, DECF and REMF evaluate their place form as specified in
        CLtS 5.1.3.
index 8dc0529..cf7562a 100644 (file)
                  ,defclass-form))))))))
 
 (defun canonize-defclass-options (class-name options)
-  (macrolet ((assert-single (option)
-               `(when ,option
-                  (error "Multiple ~A options in DEFCLASS ~S."
-                         ,(intern (string option) :keyword)
-                         class-name))))
-    (let (metaclass 
-          default-initargs
-          documentation
-          canonized-options)
+  (maplist (lambda (sublist)
+             (let ((option-name (first (pop sublist))))
+               (when (member option-name sublist :key #'first)
+                 (error "Multiple ~S options in DEFCLASS ~S." 
+                        option-name class-name))))
+           options)
+  (let (metaclass 
+        default-initargs
+        documentation
+        canonized-options)
       (dolist (option options)
         (unless (listp option)
           (error "~S is not a legal defclass option." option))
         (case (first option)
           (:metaclass 
-           (assert-single metaclass)
            (let ((maybe-metaclass (second option)))
              (unless (and maybe-metaclass (legal-class-name-p maybe-metaclass))
                (error "~@<The value of the :metaclass option (~S) ~
                       maybe-metaclass))
              (setf metaclass maybe-metaclass)))
           (:default-initargs
-           (assert-single default-initargs)
            (let (initargs arg-names)
              (doplist (key val) (cdr option)
                (when (member key arg-names)
                  (error 'simple-program-error 
                         :format-control "~@<Duplicate initialization argument ~
-                                         name ~S in :DEFAULT-INITARGS of ~
-                                         DEFCLASS ~S.~:>" 
+                                           name ~S in :DEFAULT-INITARGS of ~
+                                           DEFCLASS ~S.~:>" 
                         :format-arguments (list key class-name)))
                (push key arg-names)
                (push ``(,',key ,,(make-initfunction val) ,',val) initargs))
              (push `(:direct-default-initargs (list ,@(nreverse initargs))) 
                    canonized-options)))
           (:documentation
-           (assert-single documentation)
            (unless (stringp (second option))
              (error "~S is not a legal :documentation value" (second option)))
            (setf documentation t)
            (push `(:documentation ,(second option)) canonized-options))
           (otherwise
            (push `(',(car option) ',(cdr option)) canonized-options))))
-      (values (or metaclass 'standard-class) (nreverse canonized-options)))))
+      (values (or metaclass 'standard-class) (nreverse canonized-options))))
 
 (defun canonize-defclass-slots (class-name slots env)
   (let (canonized-specs)
index c510eb1..28fccf3 100644 (file)
   (assert (= 1 (length subs)))
   (assert (eq (car subs) (find-class 'bug-331-sub))))
 
+;;; detection of multiple class options in defclass, reported by Bruno Haible
+(defclass option-class (standard-class)
+  ((option :accessor cl-option :initarg :my-option)))
+(defmethod sb-pcl:validate-superclass ((c1 option-class) (c2 standard-class))
+  t)
+(multiple-value-bind (result error)
+    (ignore-errors (eval '(defclass option-class-instance ()
+                           ()
+                           (:my-option bar)
+                           (:my-option baz)
+                           (:metaclass option-class))))
+  (assert (not result))
+  (assert error))
+                         
 \f
 ;;;; success
 (sb-ext:quit :unix-status 104)
index 8c0088c..7a34c68 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.8.17.9"
+"0.8.17.10"