0.6.11.7:
[sbcl.git] / src / compiler / proclaim.lisp
1 ;;;; This file contains load-time support for declaration processing.
2 ;;;; In CMU CL it was split off from the compiler so that the compiler
3 ;;;; doesn't have to be in the cold load, but in SBCL the compiler is
4 ;;;; in the cold load again, so this might not be valuable.
5
6 ;;;; This software is part of the SBCL system. See the README file for
7 ;;;; more information.
8 ;;;;
9 ;;;; This software is derived from the CMU CL system, which was
10 ;;;; written at Carnegie Mellon University and released into the
11 ;;;; public domain. The software is in the public domain and is
12 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
13 ;;;; files for more information.
14
15 (in-package "SB!C")
16
17 ;;; A list of UNDEFINED-WARNING structures representing references to unknown
18 ;;; stuff which came up in a compilation unit.
19 (defvar *undefined-warnings*)
20 (declaim (list *undefined-warnings*))
21
22 ;;; Check that NAME is a valid function name, returning the name if
23 ;;; OK, and doing an error if not. In addition to checking for basic
24 ;;; well-formedness, we also check that symbol names are not NIL or
25 ;;; the name of a special form.
26 (defun check-function-name (name)
27   (typecase name
28     (list
29      (unless (and (consp name) (consp (cdr name))
30                   (null (cddr name)) (eq (car name) 'setf)
31                   (symbolp (cadr name)))
32        (compiler-error "illegal function name: ~S" name))
33      name)
34     (symbol
35      (when (eq (info :function :kind name) :special-form)
36        (compiler-error "Special form is an illegal function name: ~S" name))
37      name)
38     (t
39      (compiler-error "illegal function name: ~S" name))))
40
41 ;;; This is called to do something about SETF functions that overlap
42 ;;; with SETF macros. Perhaps we should interact with the user to see
43 ;;; whether the macro should be blown away, but for now just give a
44 ;;; warning. Due to the weak semantics of the (SETF FUNCTION) name, we
45 ;;; can't assume that they aren't just naming a function (SETF FOO)
46 ;;; for the heck of it. NAME is already known to be well-formed.
47 (defun note-if-setf-function-and-macro (name)
48   (when (consp name)
49     (when (or (info :setf :inverse name)
50               (info :setf :expander name))
51       (compiler-style-warning
52        "defining as a SETF function a name that already has a SETF macro:~
53        ~%  ~S"
54        name)))
55   (values))
56
57 ;;; Look up some symbols in *FREE-VARIABLES*, returning the var
58 ;;; structures for any which exist. If any of the names aren't
59 ;;; symbols, we complain.
60 (declaim (ftype (function (list) list) get-old-vars))
61 (defun get-old-vars (names)
62   (collect ((vars))
63     (dolist (name names (vars))
64       (unless (symbolp name)
65         (compiler-error "The name ~S is not a symbol." name))
66       (let ((old (gethash name *free-variables*)))
67         (when old (vars old))))))
68
69 ;;; Return a new POLICY containing the policy information represented
70 ;;; by the optimize declaration SPEC. Any parameters not specified are
71 ;;; defaulted from the POLICY argument.
72 (declaim (ftype (function (list policy) policy) process-optimize-decl))
73 (defun process-optimize-decl (spec policy)
74   (let ((result nil))
75     ;; Add new entries from SPEC.
76     (dolist (q-and-v-or-just-q (cdr spec))
77       (multiple-value-bind (quality raw-value)
78           (if (atom q-and-v-or-just-q)
79               (values q-and-v-or-just-q 3)
80               (destructuring-bind (quality raw-value) q-and-v-or-just-q
81                 (values quality raw-value)))
82         (cond ((not (policy-quality-name-p quality))
83                (compiler-warning "ignoring unknown optimization quality ~
84                                  ~S in ~S"
85                                  quality spec))
86               ((not (and (typep raw-value 'real) (<= 0 raw-value 3)))
87                (compiler-warning "ignoring bad optimization value ~S in ~S"
88                                  raw-value spec))
89               (t
90                (push (cons quality (rational raw-value))
91                      result)))))
92     ;; Add any nonredundant entries from old POLICY.
93     (dolist (old-entry policy)
94       (unless (assq (car old-entry) result)
95         (push old-entry result)))
96     ;; Voila.
97     result))
98
99 ;;; ANSI defines the declaration (FOO X Y) to be equivalent to
100 ;;; (TYPE FOO X Y) when FOO is a type specifier. This function
101 ;;; implements that by converting (FOO X Y) to (TYPE FOO X Y).
102 (defun canonized-decl-spec (decl-spec)
103   (let ((id (first decl-spec)))
104     (unless (symbolp id)
105       (error "The declaration identifier is not a symbol: ~S" id))
106     (let ((id-is-type (info :type :kind id))
107           (id-is-declared-decl (info :declaration :recognized id)))
108       (cond ((and id-is-type id-is-declared-decl)
109              (compiler-error
110               "ambiguous declaration ~S:~%  ~
111               ~S was declared as a DECLARATION, but is also a type name."
112               decl-spec id))
113             (id-is-type
114              (cons 'type decl-spec))
115             (t
116              decl-spec)))))
117
118 (defun sb!xc:proclaim (raw-form)
119   (let* ((form (canonized-decl-spec raw-form))
120          (kind (first form))
121          (args (rest form)))
122     (case kind
123       (special
124        (dolist (name args)
125          (unless (symbolp name)
126            (error "can't declare a non-symbol as SPECIAL: ~S" name))
127          (when (constantp name)
128            (error "can't declare a constant as SPECIAL: ~S" name))
129          (clear-info :variable :constant-value name)
130          (setf (info :variable :kind name) :special)))
131       (type
132        (when *type-system-initialized*
133          (let ((type (specifier-type (first args))))
134            (dolist (name (rest args))
135              (unless (symbolp name)
136                (error "can't declare TYPE of a non-symbol: ~S" name))
137              (when (eq (info :variable :where-from name) :declared)
138                (let ((old-type (info :variable :type name)))
139                  (when (type/= type old-type)
140                    (style-warn "The new TYPE proclamation~%  ~S~@
141                                for ~S does not match the old TYPE~@
142                                proclamation ~S"
143                                type name old-type))))
144              (setf (info :variable :type name) type)
145              (setf (info :variable :where-from name) :declared)))))
146       (ftype
147        ;; FIXME: Since currently *TYPE-SYSTEM-INITIALIZED* is not set
148        ;; until many toplevel forms have run, this condition on
149        ;; PROCLAIM (FTYPE ..) (and on PROCLAIM (TYPE ..), above) means
150        ;; that valid PROCLAIMs in cold code could get lost. Probably
151        ;; the cleanest way to deal with this would be to initialize
152        ;; the type system completely in special cold init forms,
153        ;; before any ordinary toplevel forms run. Failing that, we
154        ;; could queue up PROCLAIMs to be done after the type system is
155        ;; initialized. Failing that, we could at least issue a warning
156        ;; when we have to ignore a PROCLAIM because the type system is
157        ;; uninitialized.
158        (when *type-system-initialized*
159          (let ((type (specifier-type (first args))))
160            (unless (csubtypep type (specifier-type 'function))
161              (error "not a function type: ~S" (first args)))
162            (dolist (name (rest args))
163              (cond ((info :function :accessor-for name)
164                     ;; FIXME: This used to be a WARNING, which was
165                     ;; clearly wrong, since it would cause warnings to
166                     ;; be issued for conforming code, which is really
167                     ;; annoying for people who use Lisp code to build
168                     ;; Lisp systems (and check the return values from
169                     ;; COMPILE and COMPILE-FILE). Changing it to a
170                     ;; compiler note is somewhat better, since it's
171                     ;; after all news about a limitation of the
172                     ;; compiler, not a problem in the code. But even
173                     ;; better would be to handle FTYPE proclamations
174                     ;; for slot accessors, and since in the long run
175                     ;; slot accessors should become more like other
176                     ;; functions, this should eventually become
177                     ;; straightforward.
178                     (maybe-compiler-note
179                      "~@<ignoring FTYPE proclamation for ~
180                       slot accessor (currently unsupported): ~2I~_~S~:>"
181                      name))
182                    (t
183
184                     ;; KLUDGE: Something like the commented-out TYPE/=
185                     ;; check here would be nice, but it has been
186                     ;; commented out because TYPE/= doesn't support
187                     ;; function types. It could probably be made to do
188                     ;; so, but it might take some time, since function
189                     ;; types involve values types, which aren't
190                     ;; supported, and since the SUBTYPEP operator for
191                     ;; FUNCTION types is rather broken, e.g.
192                     ;;   (SUBTYPEP '(FUNCTION (T BOOLEAN) NIL)
193                     ;;             '(FUNCTION (FIXNUM FIXNUM) NIL)) => T, T
194                     ;; -- WHN 20000229
195                     #+nil
196                     (when (eq (info :function :where-from name) :declared)
197                       (let ((old-type (info :function :type name)))
198                         (when (type/= type old-type)
199                           (style-warn "new FTYPE proclamation~@
200                                        ~S~@
201                                        for ~S does not match old FTYPE proclamation~@
202                                        ~S"
203                                       (list type name old-type)))))
204
205                     (proclaim-as-function-name name)
206                     (note-name-defined name :function)
207                     (setf (info :function :type name) type
208                           (info :function :where-from name) :declared)))))))
209       (freeze-type
210        (dolist (type args)
211          (let ((class (specifier-type type)))
212            (when (typep class 'class)
213              (setf (class-state class) :sealed)
214              (let ((subclasses (class-subclasses class)))
215                (when subclasses
216                  (dohash (subclass layout subclasses)
217                    (declare (ignore layout))
218                    (setf (class-state subclass) :sealed))))))))
219       (optimize
220        (setq *policy* (process-optimize-decl form *policy*)))
221       (optimize-interface
222        (setq *interface-policy*
223              (process-optimize-decl form *interface-policy*)))
224       ((inline notinline maybe-inline)
225        (dolist (name args)
226          (proclaim-as-function-name name)
227          (setf (info :function :inlinep name)
228                (case kind
229                  (inline :inline)
230                  (notinline :notinline)
231                  (maybe-inline :maybe-inline)))))
232       (declaration
233        (dolist (decl args)
234          (unless (symbolp decl)
235            (error "In~%  ~S~%the declaration to be recognized is not a ~
236                   symbol:~%  ~S"
237                   form decl))
238          (setf (info :declaration :recognized decl) t)))
239       (t
240        (unless (info :declaration :recognized kind)
241          (compiler-warning "unrecognized declaration ~S" raw-form)))))
242   (values))