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 (compiler-warn "ignoring unknown optimization quality ~
51 ((not (typep raw-value
'policy-quality
))
52 (compiler-warn "ignoring bad optimization value ~S in ~S"
55 ;; we can't do this yet, because CLOS macros expand
56 ;; into code containing INHIBIT-WARNINGS.
58 (when (eql quality
'sb
!ext
:inhibit-warnings
)
59 (compiler-style-warn "~S is deprecated: use ~S instead"
60 quality
'sb
!ext
:muffle-conditions
))
61 (push (cons quality raw-value
)
63 ;; Add any nonredundant entries from old POLICY.
64 (dolist (old-entry policy
)
65 (unless (assq (car old-entry
) result
)
66 (push old-entry result
)))
70 (declaim (ftype (function (list list
) list
)
71 process-handle-conditions-decl
))
72 (defun process-handle-conditions-decl (spec list
)
73 (let ((new (copy-alist list
)))
74 (dolist (clause (cdr spec
))
75 (destructuring-bind (typespec restart-name
) clause
76 (let ((ospec (rassoc restart-name new
:test
#'eq
)))
80 (type-union (specifier-type (car ospec
))
81 (specifier-type typespec
))))
82 (push (cons (type-specifier (specifier-type typespec
))
86 (declaim (ftype (function (list list
) list
)
87 process-muffle-conditions-decl
))
88 (defun process-muffle-conditions-decl (spec list
)
89 (process-handle-conditions-decl
90 (cons 'handle-conditions
91 (mapcar (lambda (x) (list x
'muffle-warning
)) (cdr spec
)))
94 (declaim (ftype (function (list list
) list
)
95 process-unhandle-conditions-decl
))
96 (defun process-unhandle-conditions-decl (spec list
)
97 (let ((new (copy-alist list
)))
98 (dolist (clause (cdr spec
))
99 (destructuring-bind (typespec restart-name
) clause
100 (let ((ospec (rassoc restart-name new
:test
#'eq
)))
102 (let ((type-specifier
105 (specifier-type (car ospec
))
106 (specifier-type `(not ,typespec
))))))
108 (setf (car ospec
) type-specifier
)
110 (delete restart-name new
:test
#'eq
:key
#'cdr
))))
114 (declaim (ftype (function (list list
) list
)
115 process-unmuffle-conditions-decl
))
116 (defun process-unmuffle-conditions-decl (spec list
)
117 (process-unhandle-conditions-decl
118 (cons 'unhandle-conditions
119 (mapcar (lambda (x) (list x
'muffle-warning
)) (cdr spec
)))
122 (declaim (ftype (function (list list
) list
)
123 process-package-lock-decl
))
124 (defun process-package-lock-decl (spec old
)
125 (let ((decl (car spec
))
128 (disable-package-locks
129 (union old list
:test
#'equal
))
130 (enable-package-locks
131 (set-difference old list
:test
#'equal
)))))
133 ;;; ANSI defines the declaration (FOO X Y) to be equivalent to
134 ;;; (TYPE FOO X Y) when FOO is a type specifier. This function
135 ;;; implements that by converting (FOO X Y) to (TYPE FOO X Y).
136 (defun canonized-decl-spec (decl-spec)
137 (let ((id (first decl-spec
)))
138 (let ((id-is-type (if (symbolp id
)
139 (info :type
:kind id
)
140 ;; A cons might not be a valid type specifier,
141 ;; but it can't be a declaration either.
144 (id-is-declared-decl (info :declaration
:recognized id
)))
145 ;; FIXME: Checking ID-IS-DECLARED is probably useless these days,
146 ;; since we refuse to use the same symbol as both a type name and
147 ;; recognized declaration name.
148 (cond ((and id-is-type id-is-declared-decl
)
150 "ambiguous declaration ~S:~% ~
151 ~S was declared as a DECLARATION, but is also a type name."
154 (cons 'type decl-spec
))
158 (defvar *queued-proclaims
*) ; initialized in !COLD-INIT-FORMS
160 (!begin-collecting-cold-init-forms
)
161 (!cold-init-forms
(setf *queued-proclaims
* nil
))
162 (!defun-from-collected-cold-init-forms
!early-proclaim-cold-init
)
164 (defun sb!xc
:proclaim
(raw-form)
165 #+sb-xc
(/show0
"entering PROCLAIM, RAW-FORM=..")
166 #+sb-xc
(/hexstr raw-form
)
167 (let* ((form (canonized-decl-spec raw-form
))
173 (unless (symbolp name
)
174 (error "can't declare a non-symbol as SPECIAL: ~S" name
))
175 (when (sb!xc
:constantp name
)
176 (error "can't declare a constant as SPECIAL: ~S" name
))
177 (with-single-package-locked-error
178 (:symbol name
"globally declaring ~A special"))
179 (clear-info :variable
:constant-value name
)
180 (setf (info :variable
:kind name
) :special
)))
182 (if *type-system-initialized
*
183 (let ((type (specifier-type (first args
))))
184 (dolist (name (rest args
))
185 (unless (symbolp name
)
186 (error "can't declare TYPE of a non-symbol: ~S" name
))
187 (with-single-package-locked-error
188 (:symbol name
"globally declaring the type of ~A"))
189 (when (eq (info :variable
:where-from name
) :declared
)
190 (let ((old-type (info :variable
:type name
)))
191 (when (type/= type old-type
)
192 (style-warn "The new TYPE proclamation~% ~S~@
193 for ~S does not match the old TYPE~@
195 type name old-type
))))
196 (setf (info :variable
:type name
) type
)
197 (setf (info :variable
:where-from name
) :declared
)))
198 (push raw-form
*queued-proclaims
*)))
200 (if *type-system-initialized
*
201 (let ((ctype (specifier-type (first args
))))
202 (unless (csubtypep ctype
(specifier-type 'function
))
203 (error "not a function type: ~S" (first args
)))
204 (dolist (name (rest args
))
205 (with-single-package-locked-error
206 (:symbol name
"globally declaring the ftype of ~A"))
207 (when (eq (info :function
:where-from name
) :declared
)
208 (let ((old-type (info :function
:type name
)))
209 (when (type/= ctype old-type
)
211 "new FTYPE proclamation~@
213 for ~S does not match old FTYPE proclamation~@
215 ctype name old-type
))))
217 ;; Now references to this function shouldn't be warned
218 ;; about as undefined, since even if we haven't seen a
219 ;; definition yet, we know one is planned.
221 ;; Other consequences of we-know-you're-a-function-now
222 ;; are appropriate too, e.g. any MACRO-FUNCTION goes away.
223 (proclaim-as-fun-name name
)
224 (note-name-defined name
:function
)
226 ;; the actual type declaration
227 (setf (info :function
:type name
) ctype
228 (info :function
:where-from name
) :declared
)))
229 (push raw-form
*queued-proclaims
*)))
232 (let ((class (specifier-type type
)))
233 (when (typep class
'classoid
)
234 (setf (classoid-state class
) :sealed
)
235 (let ((subclasses (classoid-subclasses class
)))
237 (dohash (subclass layout subclasses
)
238 (declare (ignore layout
))
239 (setf (classoid-state subclass
) :sealed
))))))))
241 (setq *policy
* (process-optimize-decl form
*policy
*)))
243 (setq *handled-conditions
*
244 (process-muffle-conditions-decl form
*handled-conditions
*)))
246 (setq *handled-conditions
*
247 (process-unmuffle-conditions-decl form
*handled-conditions
*)))
248 ((disable-package-locks enable-package-locks
)
249 (setq *disabled-package-locks
*
250 (process-package-lock-decl form
*disabled-package-locks
*)))
251 ((inline notinline maybe-inline
)
253 (proclaim-as-fun-name name
) ; since implicitly it is a function
254 (setf (info :function
:inlinep name
)
257 (notinline :notinline
)
258 (maybe-inline :maybe-inline
)))))
261 (unless (symbolp decl
)
262 (error "In~% ~S~%the declaration to be recognized is not a ~
265 (with-single-package-locked-error
266 (:symbol decl
"globally declaring ~A as a declaration proclamation"))
267 (setf (info :declaration
:recognized decl
) t
)))
269 (unless (info :declaration
:recognized kind
)
270 (compiler-warn "unrecognized declaration ~S" raw-form
)))))
271 #+sb-xc
(/show0
"returning from PROCLAIM")