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 (declaim (ftype (function (list list
) list
)
35 process-handle-conditions-decl
))
36 (defun process-handle-conditions-decl (spec list
)
37 (let ((new (copy-alist list
)))
38 (dolist (clause (cdr spec
) new
)
39 (destructuring-bind (typespec restart-name
) clause
40 (let ((type (compiler-specifier-type typespec
))
41 (ospec (rassoc restart-name new
:test
#'eq
)))
43 (setf (car ospec
) (type-union (car ospec
) type
))
44 (push (cons type restart-name
) new
)))))))
46 (declaim (ftype (function (list list
) list
)
47 process-muffle-conditions-decl
))
48 (defun process-muffle-conditions-decl (spec list
)
49 (process-handle-conditions-decl
50 `(handle-conditions ((or ,@(cdr spec
)) muffle-warning
))
53 (declaim (ftype (function (list list
) list
)
54 process-unhandle-conditions-decl
))
55 (defun process-unhandle-conditions-decl (spec list
)
56 (let ((new (copy-alist list
)))
57 (dolist (clause (cdr spec
) new
)
58 (destructuring-bind (typespec restart-name
) clause
59 (let ((ospec (rassoc restart-name new
:test
#'eq
)))
61 (let ((type (type-intersection
63 (compiler-specifier-type `(not ,typespec
)))))
64 (if (type= type
*empty-type
*)
65 (setq new
(delete restart-name new
:test
#'eq
:key
#'cdr
))
66 (setf (car ospec
) type
)))
70 (declaim (ftype (function (list list
) list
)
71 process-unmuffle-conditions-decl
))
72 (defun process-unmuffle-conditions-decl (spec list
)
73 (process-unhandle-conditions-decl
74 `(unhandle-conditions ((or ,@(cdr spec
)) muffle-warning
))
77 (declaim (ftype (function (list list
) list
)
78 process-package-lock-decl
))
79 (defun process-package-lock-decl (spec old
)
80 (destructuring-bind (decl &rest names
) spec
82 (disable-package-locks
83 (union old names
:test
#'equal
))
85 (set-difference old names
:test
#'equal
)))))
87 (!defvar
*queued-proclaims
* nil
) ; should this be !*QUEUED-PROCLAIMS* ?
89 (defun process-variable-declaration (name kind info-value
)
90 (unless (symbolp name
)
91 (error "Cannot proclaim a non-symbol as ~A: ~S" kind name
))
93 (when (and (eq kind
'always-bound
) (eq info-value
:always-bound
)
95 (error "Cannot proclaim an unbound symbol as ~A: ~S" kind name
))
97 (multiple-value-bind (allowed test
)
99 (special (values '(:special
:unknown
) #'eq
))
100 (global (values '(:global
:unknown
) #'eq
))
101 (always-bound (values '(:constant
) #'neq
)))
102 (let ((old (info :variable
:kind name
)))
103 (unless (member old allowed
:test test
)
104 (error "Cannot proclaim a ~A variable ~A: ~S" old kind name
))))
106 (with-single-package-locked-error
107 (:symbol name
"globally declaring ~A ~A" kind
)
108 (if (eq kind
'always-bound
)
109 (setf (info :variable
:always-bound name
) info-value
)
110 (setf (info :variable
:kind name
) info-value
))))
112 (defun proclaim-type (name type type-specifier where-from
)
113 (unless (symbolp name
)
114 (error "Cannot proclaim TYPE of a non-symbol: ~S" name
))
116 (with-single-package-locked-error
117 (:symbol name
"globally declaring the TYPE of ~A")
118 (when (eq (info :variable
:where-from name
) :declared
)
119 (let ((old-type (info :variable
:type name
)))
120 (when (type/= type old-type
)
121 (type-proclamation-mismatch-warn
122 name
(type-specifier old-type
) type-specifier
))))
123 (setf (info :variable
:type name
) type
124 (info :variable
:where-from name
) where-from
)))
126 (defun proclaim-ftype (name type type-specifier where-from
)
127 (unless (legal-fun-name-p name
)
128 (error "Cannot declare FTYPE of illegal function name ~S" name
))
129 (unless (csubtypep type
(specifier-type 'function
))
130 (error "Not a function type: ~S" (type-specifier type
)))
132 (with-single-package-locked-error
133 (:symbol name
"globally declaring the FTYPE of ~A")
134 (when (eq (info :function
:where-from name
) :declared
)
135 (let ((old-type (info :function
:type name
)))
137 ((not (type/= type old-type
))) ; not changed
138 ((not (info :function
:info name
)) ; not a known function
139 (ftype-proclamation-mismatch-warn
140 name
(type-specifier old-type
) type-specifier
))
141 ((csubtypep type old-type
)) ; tighten known function type
144 'ftype-proclamation-mismatch-error
146 :old
(type-specifier old-type
)
147 :new type-specifier
)))))
148 ;; Now references to this function shouldn't be warned about as
149 ;; undefined, since even if we haven't seen a definition yet, we
150 ;; know one is planned.
152 ;; Other consequences of we-know-you're-a-function-now are
153 ;; appropriate too, e.g. any MACRO-FUNCTION goes away.
154 (proclaim-as-fun-name name
)
155 (note-name-defined name
:function
)
157 ;; The actual type declaration.
158 (setf (info :function
:type name
) type
159 (info :function
:where-from name
) where-from
)))
161 (defun seal-class (class)
162 (declare (type classoid class
))
163 (setf (classoid-state class
) :sealed
)
164 (let ((subclasses (classoid-subclasses class
)))
166 (dohash ((subclass layout
) subclasses
:locked t
)
167 (declare (ignore layout
))
168 (setf (classoid-state subclass
) :sealed
)))))
170 (defun process-freeze-type-declaration (type-specifier)
171 (let ((class (specifier-type type-specifier
)))
172 (when (typep class
'classoid
)
173 (seal-class class
))))
175 (defun process-inline-declaration (name kind
)
176 ;; since implicitly it is a function, also scrubs *FREE-FUNS*
177 (proclaim-as-fun-name name
)
178 ;; Check for problems before touching globaldb,
179 ;; so that the report function can see the old value.
183 (notinline :notinline
)
184 (maybe-inline :maybe-inline
))))
185 (warn-if-inline-failed/proclaim name newval
)
186 (setf (info :function
:inlinep name
) newval
)))
188 (defun check-deprecation-declaration (state since form
)
189 (unless (typep state
'deprecation-state
)
190 (error 'simple-type-error
192 :expected-type
'deprecation-state
193 :format-control
"~<In declaration ~S, ~S state is not a ~
194 valid deprecation state. Expected one ~
196 :format-arguments
(list form state
197 (rest (typexpand 'deprecation-state
)))))
198 (multiple-value-call #'values
199 state
(sb!impl
::normalize-deprecation-since since
)))
201 (defun process-deprecation-declaration (thing state software version
)
202 (destructuring-bind (namespace name
&key replacement
) thing
203 (let ((info (make-deprecation-info state software version replacement
)))
206 (when (eq state
:final
)
207 (sb!impl
::setup-function-in-final-deprecation
208 software version name replacement
))
209 (setf (info :function
:deprecated name
) info
))
211 ;; TODO (check-variable-name name "deprecated variable declaration")
212 (when (eq state
:final
)
213 (sb!impl
::setup-variable-in-final-deprecation
214 software version name replacement
))
215 (setf (info :variable
:deprecated name
) info
))
217 (when (eq state
:final
)
218 (sb!impl
::setup-type-in-final-deprecation
219 software version name replacement
))
220 (setf (info :type
:deprecated name
) info
))))))
222 (defun process-declaration-declaration (name form
)
223 (unless (symbolp name
)
224 (error "In~% ~S~%the declaration to be recognized is not a ~
227 (with-single-package-locked-error
228 (:symbol name
"globally declaring ~A as a declaration proclamation"))
229 (setf (info :declaration
:recognized name
) t
))
231 ;;; ANSI defines the declaration (FOO X Y) to be equivalent to
232 ;;; (TYPE FOO X Y) when FOO is a type specifier. This function
233 ;;; implements that by converting (FOO X Y) to (TYPE FOO X Y).
234 (defun canonized-decl-spec (decl-spec)
235 (let ((id (first decl-spec
)))
236 (if (cond ((symbolp id
) (info :type
:kind id
))
240 (or (info :type
:translator id
)
241 (info :type
:kind id
)))))
243 ;; FIXME: should be (TYPEP id '(OR CLASS CLASSOID))
244 ;; but that references CLASS too soon.
245 ;; See related hack in DEF!TYPE TYPE-SPECIFIER.
246 (typep id
'instance
)))
247 (cons 'type decl-spec
)
250 ;; These return values are intended for EQ-comparison in
251 ;; STORE-LOCATION in %PROCLAIM.
252 (defun deprecation-location-key (namespace)
254 (function '(deprecated function
))
255 (variable '(deprecated variable
))
256 (type '(deprecated type
))))
258 (defun %proclaim
(raw-form location
)
259 (destructuring-bind (&whole form
&optional kind
&rest args
)
260 (canonized-decl-spec raw-form
)
261 (labels ((store-location (name &key
(key kind
))
263 (setf (getf (info :source-location
:declaration name
) key
)
265 (remf (info :source-location
:declaration name
) key
)))
266 (map-names (names function
&rest extra-args
)
268 (store-location name
)
269 (apply function name extra-args
))
271 (map-args (function &rest extra-args
)
272 (apply #'map-names args function extra-args
)))
274 ((special global always-bound
)
275 (map-args #'process-variable-declaration kind
279 (always-bound :always-bound
))))
281 (if *type-system-initialized
*
282 (destructuring-bind (type &rest names
) args
283 (check-deprecated-type type
)
284 (let ((ctype (specifier-type type
)))
285 (map-names names
(ecase kind
286 (type #'proclaim-type
)
287 (ftype #'proclaim-ftype
))
288 ctype type
:declared
)))
289 (push raw-form
*queued-proclaims
*)))
291 (map-args #'process-freeze-type-declaration
))
293 (multiple-value-bind (new-policy specified-qualities
)
294 (process-optimize-decl form
*policy
*)
295 (setq *policy
* new-policy
)
296 (warn-repeated-optimize-qualities new-policy specified-qualities
)))
298 (setq *handled-conditions
*
299 (process-muffle-conditions-decl form
*handled-conditions
*)))
301 (setq *handled-conditions
*
302 (process-unmuffle-conditions-decl form
*handled-conditions
*)))
303 ((disable-package-locks enable-package-locks
)
304 (setq *disabled-package-locks
*
305 (process-package-lock-decl form
*disabled-package-locks
*)))
306 ((inline notinline maybe-inline
)
307 (map-args #'process-inline-declaration kind
))
309 (destructuring-bind (state since
&rest things
) args
310 (multiple-value-bind (state software version
)
311 (check-deprecation-declaration state since form
)
312 (mapc (lambda (thing)
313 (destructuring-bind (namespace name
&rest rest
) thing
314 (declare (ignore rest
))
316 name
:key
(deprecation-location-key namespace
)))
317 (process-deprecation-declaration thing state software version
))
320 (map-args #'process-declaration-declaration form
))
322 (unless (info :declaration
:recognized kind
)
323 (compiler-warn "unrecognized declaration ~S" raw-form
)))))))
325 (defun sb!xc
:proclaim
(raw-form)
326 #+sb-xc
(/show0
"entering PROCLAIM, RAW-FORM=..")
327 #+sb-xc
(/hexstr raw-form
)
328 (%proclaim raw-form nil
)
329 #+sb-xc
(/show0
"returning from PROCLAIM")
332 ;; Issue a style warning if there are any repeated OPTIMIZE declarations
333 ;; given the SPECIFIED-QUALITIES, unless there is no ambiguity.
334 (defun warn-repeated-optimize-qualities (new-policy specified-qualities
)
336 (dolist (quality-and-value specified-qualities
)
337 (let* ((quality (car quality-and-value
))
338 (current ; Read the raw quality value, not the adjusted value.
339 (%%policy-quality new-policy
(policy-quality-name-p quality
))))
340 (when (and (not (eql (cdr quality-and-value
) current
))
341 (not (assq quality dups
)))
342 (push `(,quality
,current
) dups
))))
344 ;; If a restriction is in force, this message can be misleading,
345 ;; as the "effective" value isn't always what the message claims.
346 (compiler-style-warn "Repeated OPTIMIZE qualit~@P. Using ~{~S~^ and ~}"
347 (length dups
) dups
))))