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 (let ((deprecation-warning (policy-quality-deprecation-warning quality spec
)))
49 (if deprecation-warning
50 (compiler-warn deprecation-warning
)
51 (compiler-warn "~@<Ignoring unknown optimization quality ~S in:~_ ~S~:>"
53 ((not (typep raw-value
'policy-quality
))
54 (compiler-warn "~@<Ignoring bad optimization value ~S in:~_ ~S~:>"
57 ;; we can't do this yet, because CLOS macros expand
58 ;; into code containing INHIBIT-WARNINGS.
60 (when (eql quality
'sb
!ext
:inhibit-warnings
)
61 (compiler-style-warn "~S is deprecated: use ~S instead"
62 quality
'sb
!ext
:muffle-conditions
))
63 (push (cons quality raw-value
)
65 ;; Add any nonredundant entries from old POLICY.
66 (dolist (old-entry policy
)
67 (unless (assq (car old-entry
) result
)
68 (push old-entry result
)))
72 (declaim (ftype (function (list list
) list
)
73 process-handle-conditions-decl
))
74 (defun process-handle-conditions-decl (spec list
)
75 (let ((new (copy-alist list
)))
76 (dolist (clause (cdr spec
))
77 (destructuring-bind (typespec restart-name
) clause
78 (let ((ospec (rassoc restart-name new
:test
#'eq
)))
82 (type-union (specifier-type (car ospec
))
83 (specifier-type typespec
))))
84 (push (cons (type-specifier (specifier-type typespec
))
88 (declaim (ftype (function (list list
) list
)
89 process-muffle-conditions-decl
))
90 (defun process-muffle-conditions-decl (spec list
)
91 (process-handle-conditions-decl
92 (cons 'handle-conditions
93 (mapcar (lambda (x) (list x
'muffle-warning
)) (cdr spec
)))
96 (declaim (ftype (function (list list
) list
)
97 process-unhandle-conditions-decl
))
98 (defun process-unhandle-conditions-decl (spec list
)
99 (let ((new (copy-alist list
)))
100 (dolist (clause (cdr spec
))
101 (destructuring-bind (typespec restart-name
) clause
102 (let ((ospec (rassoc restart-name new
:test
#'eq
)))
104 (let ((type-specifier
107 (specifier-type (car ospec
))
108 (specifier-type `(not ,typespec
))))))
110 (setf (car ospec
) type-specifier
)
112 (delete restart-name new
:test
#'eq
:key
#'cdr
))))
116 (declaim (ftype (function (list list
) list
)
117 process-unmuffle-conditions-decl
))
118 (defun process-unmuffle-conditions-decl (spec list
)
119 (process-unhandle-conditions-decl
120 (cons 'unhandle-conditions
121 (mapcar (lambda (x) (list x
'muffle-warning
)) (cdr spec
)))
124 (declaim (ftype (function (list list
) list
)
125 process-package-lock-decl
))
126 (defun process-package-lock-decl (spec old
)
127 (let ((decl (car spec
))
130 (disable-package-locks
131 (union old list
:test
#'equal
))
132 (enable-package-locks
133 (set-difference old list
:test
#'equal
)))))
135 ;;; ANSI defines the declaration (FOO X Y) to be equivalent to
136 ;;; (TYPE FOO X Y) when FOO is a type specifier. This function
137 ;;; implements that by converting (FOO X Y) to (TYPE FOO X Y).
138 (defun canonized-decl-spec (decl-spec)
139 (let ((id (first decl-spec
)))
140 (let ((id-is-type (if (symbolp id
)
141 (info :type
:kind id
)
142 ;; A cons might not be a valid type specifier,
143 ;; but it can't be a declaration either.
146 (id-is-declared-decl (info :declaration
:recognized id
)))
147 ;; FIXME: Checking ID-IS-DECLARED is probably useless these days,
148 ;; since we refuse to use the same symbol as both a type name and
149 ;; recognized declaration name.
150 (cond ((and id-is-type id-is-declared-decl
)
152 "ambiguous declaration ~S:~% ~
153 ~S was declared as a DECLARATION, but is also a type name."
156 (cons 'type decl-spec
))
160 (defvar *queued-proclaims
*) ; initialized in !COLD-INIT-FORMS
162 (!begin-collecting-cold-init-forms
)
163 (!cold-init-forms
(setf *queued-proclaims
* nil
))
164 (!defun-from-collected-cold-init-forms
!early-proclaim-cold-init
)
166 (defun sb!xc
:proclaim
(raw-form)
167 #+sb-xc
(/show0
"entering PROCLAIM, RAW-FORM=..")
168 #+sb-xc
(/hexstr raw-form
)
169 (let* ((form (canonized-decl-spec raw-form
))
175 (unless (symbolp name
)
176 (error "can't declare a non-symbol as SPECIAL: ~S" name
))
177 (with-single-package-locked-error
178 (:symbol name
"globally declaring ~A special")
179 (about-to-modify-symbol-value name
"proclaim ~S as SPECIAL")
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 ;; FIXME: changing to TYPE-PROCLAMATION-MISMATCH
193 ;; broke late-proclaim.lisp.
194 (style-warn "The new TYPE proclamation~% ~S~@
195 for ~S does not match the old TYPE~@
197 type name old-type
))))
198 (setf (info :variable
:type name
) type
)
199 (setf (info :variable
:where-from name
) :declared
)))
200 (push raw-form
*queued-proclaims
*)))
202 (if *type-system-initialized
*
203 (let ((ctype (specifier-type (first args
))))
204 (unless (csubtypep ctype
(specifier-type 'function
))
205 (error "not a function type: ~S" (first args
)))
206 (dolist (name (rest args
))
207 (with-single-package-locked-error
208 (:symbol name
"globally declaring the ftype of ~A"))
209 (when (eq (info :function
:where-from name
) :declared
)
210 (let ((old-type (info :function
:type name
)))
211 (when (type/= ctype old-type
)
212 ;; FIXME: changing to FTYPE-PROCLAMATION-MISMATCH
213 ;; broke late-proclaim.lisp.
215 "new FTYPE proclamation~@
217 for ~S does not match old FTYPE proclamation~@
219 ctype name old-type
))))
221 ;; Now references to this function shouldn't be warned
222 ;; about as undefined, since even if we haven't seen a
223 ;; definition yet, we know one is planned.
225 ;; Other consequences of we-know-you're-a-function-now
226 ;; are appropriate too, e.g. any MACRO-FUNCTION goes away.
227 (proclaim-as-fun-name name
)
228 (note-name-defined name
:function
)
230 ;; the actual type declaration
231 (setf (info :function
:type name
) ctype
232 (info :function
:where-from name
) :declared
)))
233 (push raw-form
*queued-proclaims
*)))
236 (let ((class (specifier-type type
)))
237 (when (typep class
'classoid
)
238 (setf (classoid-state class
) :sealed
)
239 (let ((subclasses (classoid-subclasses class
)))
241 (dohash ((subclass layout
) subclasses
:locked t
)
242 (declare (ignore layout
))
243 (setf (classoid-state subclass
) :sealed
))))))))
245 (setq *policy
* (process-optimize-decl form
*policy
*)))
247 (setq *handled-conditions
*
248 (process-muffle-conditions-decl form
*handled-conditions
*)))
250 (setq *handled-conditions
*
251 (process-unmuffle-conditions-decl form
*handled-conditions
*)))
252 ((disable-package-locks enable-package-locks
)
253 (setq *disabled-package-locks
*
254 (process-package-lock-decl form
*disabled-package-locks
*)))
255 ((inline notinline maybe-inline
)
257 (proclaim-as-fun-name name
) ; since implicitly it is a function
258 (setf (info :function
:inlinep name
)
261 (notinline :notinline
)
262 (maybe-inline :maybe-inline
)))))
265 (unless (symbolp decl
)
266 (error "In~% ~S~%the declaration to be recognized is not a ~
269 (with-single-package-locked-error
270 (:symbol decl
"globally declaring ~A as a declaration proclamation"))
271 (setf (info :declaration
:recognized decl
) t
)))
273 (unless (info :declaration
:recognized kind
)
274 (compiler-warn "unrecognized declaration ~S" raw-form
)))))
275 #+sb-xc
(/show0
"returning from PROCLAIM")