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.
6 ;;;; This software is part of the SBCL system. See the README file for
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.
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*))
22 ;;; Look up some symbols in *FREE-VARS*, returning the var
23 ;;; structures for any which exist. If any of the names aren't
24 ;;; symbols, we complain.
25 (declaim (ftype (function (list) list) get-old-vars))
26 (defun get-old-vars (names)
28 (dolist (name names (vars))
29 (unless (symbolp name)
30 (compiler-error "The name ~S is not a symbol." name))
31 (let ((old (gethash name *free-vars*)))
32 (when old (vars old))))))
34 ;;; Return a new POLICY containing the policy information represented
35 ;;; by the optimize declaration SPEC. Any parameters not specified are
36 ;;; defaulted from the POLICY argument.
37 (declaim (ftype (function (list policy) policy) process-optimize-decl))
38 (defun process-optimize-decl (spec policy)
40 ;; Add new entries from SPEC.
41 (dolist (q-and-v-or-just-q (cdr spec))
42 (multiple-value-bind (quality raw-value)
43 (if (atom q-and-v-or-just-q)
44 (values q-and-v-or-just-q 3)
45 (destructuring-bind (quality raw-value) q-and-v-or-just-q
46 (values quality raw-value)))
47 (cond ((not (policy-quality-name-p quality))
48 (or (policy-quality-deprecation-warning quality)
50 "~@<Ignoring unknown optimization quality ~S in:~_ ~S~:>"
52 ((not (typep raw-value 'policy-quality))
53 (compiler-warn "~@<Ignoring bad optimization value ~S in:~_ ~S~:>"
56 ;; we can't do this yet, because CLOS macros expand
57 ;; into code containing INHIBIT-WARNINGS.
59 (when (eql quality 'sb!ext:inhibit-warnings)
60 (compiler-style-warn "~S is deprecated: use ~S instead"
61 quality 'sb!ext:muffle-conditions))
62 (push (cons quality raw-value)
64 ;; Add any nonredundant entries from old POLICY.
65 (dolist (old-entry policy)
66 (unless (assq (car old-entry) result)
67 (push old-entry result)))
69 (sort-policy result)))
71 (declaim (ftype (function (list list) list)
72 process-handle-conditions-decl))
73 (defun process-handle-conditions-decl (spec list)
74 (let ((new (copy-alist list)))
75 (dolist (clause (cdr spec))
76 (destructuring-bind (typespec restart-name) clause
77 (let ((ospec (rassoc restart-name new :test #'eq)))
81 (type-union (specifier-type (car ospec))
82 (specifier-type typespec))))
83 (push (cons (type-specifier (specifier-type typespec))
87 (declaim (ftype (function (list list) list)
88 process-muffle-conditions-decl))
89 (defun process-muffle-conditions-decl (spec list)
90 (process-handle-conditions-decl
91 (cons 'handle-conditions
92 (mapcar (lambda (x) (list x 'muffle-warning)) (cdr spec)))
95 (declaim (ftype (function (list list) list)
96 process-unhandle-conditions-decl))
97 (defun process-unhandle-conditions-decl (spec list)
98 (let ((new (copy-alist list)))
99 (dolist (clause (cdr spec))
100 (destructuring-bind (typespec restart-name) clause
101 (let ((ospec (rassoc restart-name new :test #'eq)))
103 (let ((type-specifier
106 (specifier-type (car ospec))
107 (specifier-type `(not ,typespec))))))
109 (setf (car ospec) type-specifier)
111 (delete restart-name new :test #'eq :key #'cdr))))
115 (declaim (ftype (function (list list) list)
116 process-unmuffle-conditions-decl))
117 (defun process-unmuffle-conditions-decl (spec list)
118 (process-unhandle-conditions-decl
119 (cons 'unhandle-conditions
120 (mapcar (lambda (x) (list x 'muffle-warning)) (cdr spec)))
123 (declaim (ftype (function (list list) list)
124 process-package-lock-decl))
125 (defun process-package-lock-decl (spec old)
126 (let ((decl (car spec))
129 (disable-package-locks
130 (union old list :test #'equal))
131 (enable-package-locks
132 (set-difference old list :test #'equal)))))
134 ;;; ANSI defines the declaration (FOO X Y) to be equivalent to
135 ;;; (TYPE FOO X Y) when FOO is a type specifier. This function
136 ;;; implements that by converting (FOO X Y) to (TYPE FOO X Y).
137 (defun canonized-decl-spec (decl-spec)
138 (let ((id (first decl-spec)))
139 (let ((id-is-type (if (symbolp id)
140 (info :type :kind id)
141 ;; A cons might not be a valid type specifier,
142 ;; but it can't be a declaration either.
145 (id-is-declared-decl (info :declaration :recognized id)))
146 ;; FIXME: Checking ID-IS-DECLARED is probably useless these days,
147 ;; since we refuse to use the same symbol as both a type name and
148 ;; recognized declaration name.
149 (cond ((and id-is-type id-is-declared-decl)
151 "ambiguous declaration ~S:~% ~
152 ~S was declared as a DECLARATION, but is also a type name."
155 (cons 'type decl-spec))
159 (defvar *queued-proclaims*) ; initialized in !COLD-INIT-FORMS
161 (!begin-collecting-cold-init-forms)
162 (!cold-init-forms (setf *queued-proclaims* nil))
163 (!defun-from-collected-cold-init-forms !early-proclaim-cold-init)
165 (defun sb!xc:proclaim (raw-form)
166 #+sb-xc (/show0 "entering PROCLAIM, RAW-FORM=..")
167 #+sb-xc (/hexstr raw-form)
168 (let* ((form (canonized-decl-spec raw-form))
173 (flet ((make-special (name old)
174 (unless (member old '(:special :unknown))
175 (error "Cannot proclaim a ~(~A~) variable special: ~S" old name))
176 (with-single-package-locked-error
177 (:symbol name "globally declaring ~A special")
178 (setf (info :variable :kind name) :special)))
179 (make-global (name old)
180 (unless (member old '(:global :unknown))
181 (error "Cannot proclaim a ~(~A~) variable global: ~S" old name))
182 (with-single-package-locked-error
183 (:symbol name "globally declaring ~A global")
184 (setf (info :variable :kind name) :global))))
185 (let ((fun (if (eq 'special kind) #'make-special #'make-global)))
187 (unless (symbolp name)
188 (error "Can't declare a non-symbol as ~S: ~S" kind name))
189 (funcall fun name (info :variable :kind name))))))
192 (unless (symbolp name)
193 (error "Can't proclaim a non-symbol as ~S: ~S" kind name))
194 (unless (boundp name)
195 (error "Can't proclaim an unbound symbol as ~S: ~S" kind name))
196 (when (eq :constant (info :variable :kind name))
197 (error "Can't proclaim a constant variable as ~S: ~S" kind name))
198 (with-single-package-locked-error
199 (:symbol name "globally declaring ~A always bound")
200 (setf (info :variable :always-bound name) t))))
202 (if *type-system-initialized*
203 (let ((type (specifier-type (first args))))
204 (dolist (name (rest args))
205 (unless (symbolp name)
206 (error "can't declare TYPE of a non-symbol: ~S" name))
207 (with-single-package-locked-error
208 (:symbol name "globally declaring the type of ~A"))
209 (when (eq (info :variable :where-from name) :declared)
210 (let ((old-type (info :variable :type name)))
211 (when (type/= type old-type)
212 ;; FIXME: changing to TYPE-PROCLAMATION-MISMATCH
213 ;; broke late-proclaim.lisp.
215 "~@<new TYPE proclamation for ~S~@:_ ~S~@:_~
216 does not match the old TYPE proclamation:~@:_ ~S~@:>"
217 name (type-specifier type) (type-specifier old-type)))))
218 (setf (info :variable :type name) type)
219 (setf (info :variable :where-from name) :declared)))
220 (push raw-form *queued-proclaims*)))
222 (if *type-system-initialized*
223 (let ((ctype (specifier-type (first args))))
224 (unless (csubtypep ctype (specifier-type 'function))
225 (error "not a function type: ~S" (first args)))
226 (dolist (name (rest args))
227 (with-single-package-locked-error
228 (:symbol name "globally declaring the ftype of ~A")
229 (when (eq (info :function :where-from name) :declared)
230 (let ((old-type (info :function :type name)))
231 (when (type/= ctype old-type)
232 ;; FIXME: changing to FTYPE-PROCLAMATION-MISMATCH
233 ;; broke late-proclaim.lisp.
234 (if (info :function :info name)
235 ;; Allow for tightening of known function types
236 (unless (csubtypep ctype old-type)
238 "~@<new FTYPE proclamation for known function ~S~@:_ ~S~@:_~
239 does not match its old FTYPE:~@:_ ~S~@:>"
240 name (type-specifier ctype) (type-specifier old-type)))
242 #-sb-xc-host style-warn
243 "~@<new FTYPE proclamation for ~S~@:_ ~S~@:_~
244 does not match the old FTYPE proclamation:~@:_ ~S~@:>"
245 name (type-specifier ctype) (type-specifier old-type))))))
246 ;; Now references to this function shouldn't be warned
247 ;; about as undefined, since even if we haven't seen a
248 ;; definition yet, we know one is planned.
250 ;; Other consequences of we-know-you're-a-function-now
251 ;; are appropriate too, e.g. any MACRO-FUNCTION goes away.
252 (proclaim-as-fun-name name)
253 (note-name-defined name :function)
255 ;; the actual type declaration
256 (setf (info :function :type name) ctype
257 (info :function :where-from name) :declared))))
258 (push raw-form *queued-proclaims*)))
261 (let ((class (specifier-type type)))
262 (when (typep class 'classoid)
263 (setf (classoid-state class) :sealed)
264 (let ((subclasses (classoid-subclasses class)))
266 (dohash ((subclass layout) subclasses :locked t)
267 (declare (ignore layout))
268 (setf (classoid-state subclass) :sealed))))))))
270 (setq *policy* (process-optimize-decl form *policy*)))
272 (setq *handled-conditions*
273 (process-muffle-conditions-decl form *handled-conditions*)))
275 (setq *handled-conditions*
276 (process-unmuffle-conditions-decl form *handled-conditions*)))
277 ((disable-package-locks enable-package-locks)
278 (setq *disabled-package-locks*
279 (process-package-lock-decl form *disabled-package-locks*)))
280 ((inline notinline maybe-inline)
282 ; since implicitly it is a function, also scrubs *FREE-FUNS*
283 (proclaim-as-fun-name name)
284 (setf (info :function :inlinep name)
287 (notinline :notinline)
288 (maybe-inline :maybe-inline)))))
291 (unless (symbolp decl)
292 (error "In~% ~S~%the declaration to be recognized is not a ~
295 (with-single-package-locked-error
296 (:symbol decl "globally declaring ~A as a declaration proclamation"))
297 (setf (info :declaration :recognized decl) t)))
299 (unless (info :declaration :recognized kind)
300 (compiler-warn "unrecognized declaration ~S" raw-form)))))
301 #+sb-xc (/show0 "returning from PROCLAIM")