0.8.3.66:
[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 ;;; 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)
27   (collect ((vars))
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))))))
33
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)
39   (let ((result nil))
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 ~
49                                ~S in ~S"
50                                quality spec))
51               ((not (typep raw-value 'policy-quality))
52                (compiler-warn "ignoring bad optimization value ~S in ~S"
53                               raw-value spec))
54               (t
55                (push (cons quality raw-value)
56                      result)))))
57     ;; Add any nonredundant entries from old POLICY.
58     (dolist (old-entry policy)
59       (unless (assq (car old-entry) result)
60         (push old-entry result)))
61     ;; Voila.
62     result))
63
64 ;;; ANSI defines the declaration (FOO X Y) to be equivalent to
65 ;;; (TYPE FOO X Y) when FOO is a type specifier. This function
66 ;;; implements that by converting (FOO X Y) to (TYPE FOO X Y).
67 (defun canonized-decl-spec (decl-spec)
68   (let ((id (first decl-spec)))
69     (unless (symbolp id)
70       (error "The declaration identifier is not a symbol: ~S" id))
71     (let ((id-is-type (info :type :kind id))
72           (id-is-declared-decl (info :declaration :recognized id)))
73       (cond ((and id-is-type id-is-declared-decl)
74              (compiler-error
75               "ambiguous declaration ~S:~%  ~
76               ~S was declared as a DECLARATION, but is also a type name."
77               decl-spec id))
78             (id-is-type
79              (cons 'type decl-spec))
80             (t
81              decl-spec)))))
82
83 (defvar *queued-proclaims*) ; initialized in !COLD-INIT-FORMS
84
85 (!begin-collecting-cold-init-forms)
86 (!cold-init-forms (setf *queued-proclaims* nil))
87 (!defun-from-collected-cold-init-forms !early-proclaim-cold-init)
88
89 (defun sb!xc:proclaim (raw-form)
90   #+sb-xc (/show0 "entering PROCLAIM, RAW-FORM=..")
91   #+sb-xc (/hexstr raw-form)
92   (let* ((form (canonized-decl-spec raw-form))
93          (kind (first form))
94          (args (rest form)))
95     (case kind
96       (special
97        (dolist (name args)
98          (unless (symbolp name)
99            (error "can't declare a non-symbol as SPECIAL: ~S" name))
100          (when (constantp name)
101            (error "can't declare a constant as SPECIAL: ~S" name))
102          (clear-info :variable :constant-value name)
103          (setf (info :variable :kind name) :special)))
104       (type
105        (if *type-system-initialized*
106            (let ((type (specifier-type (first args))))
107              (dolist (name (rest args))
108                (unless (symbolp name)
109                  (error "can't declare TYPE of a non-symbol: ~S" name))
110                (when (eq (info :variable :where-from name) :declared)
111                  (let ((old-type (info :variable :type name)))
112                    (when (type/= type old-type)
113                      (style-warn "The new TYPE proclamation~%  ~S~@
114                                   for ~S does not match the old TYPE~@
115                                   proclamation ~S"
116                                  type name old-type))))
117                (setf (info :variable :type name) type)
118                (setf (info :variable :where-from name) :declared)))
119            (push raw-form *queued-proclaims*)))
120       (ftype
121        (if *type-system-initialized*
122            (let ((ctype (specifier-type (first args))))
123              (unless (csubtypep ctype (specifier-type 'function))
124                (error "not a function type: ~S" (first args)))
125              (dolist (name (rest args))
126                (when (eq (info :function :where-from name) :declared)
127                  (let ((old-type (info :function :type name)))
128                    (when (type/= ctype old-type)
129                      (style-warn
130                       "new FTYPE proclamation~@
131                        ~S~@
132                        for ~S does not match old FTYPE proclamation~@
133                        ~S"
134                       ctype name old-type))))
135
136                ;; Now references to this function shouldn't be warned
137                ;; about as undefined, since even if we haven't seen a
138                ;; definition yet, we know one is planned.
139                ;;
140                ;; Other consequences of we-know-you're-a-function-now
141                ;; are appropriate too, e.g. any MACRO-FUNCTION goes away.
142                (proclaim-as-fun-name name)
143                (note-name-defined name :function)
144
145                ;; the actual type declaration
146                (setf (info :function :type name) ctype
147                      (info :function :where-from name) :declared)))
148            (push raw-form *queued-proclaims*)))
149       (freeze-type
150        (dolist (type args)
151          (let ((class (specifier-type type)))
152            (when (typep class 'classoid)
153              (setf (classoid-state class) :sealed)
154              (let ((subclasses (classoid-subclasses class)))
155                (when subclasses
156                  (dohash (subclass layout subclasses)
157                    (declare (ignore layout))
158                    (setf (classoid-state subclass) :sealed))))))))
159       (optimize
160        (setq *policy* (process-optimize-decl form *policy*)))
161       ((inline notinline maybe-inline)
162        (dolist (name args)
163          (proclaim-as-fun-name name) ; since implicitly it is a function
164          (setf (info :function :inlinep name)
165                (ecase kind
166                  (inline :inline)
167                  (notinline :notinline)
168                  (maybe-inline :maybe-inline)))))
169       (declaration
170        (dolist (decl args)
171          (unless (symbolp decl)
172            (error "In~%  ~S~%the declaration to be recognized is not a ~
173                   symbol:~%  ~S"
174                   form decl))
175          (setf (info :declaration :recognized decl) t)))
176       (t
177        (unless (info :declaration :recognized kind)
178          (compiler-warn "unrecognized declaration ~S" raw-form)))))
179   #+sb-xc (/show0 "returning from PROCLAIM")
180   (values))