Scope local muffling declarations correctly for undefined variables.

Previously on high debug, any muffling, no matter where it was scoped,
would kill any undefined variable warning. Even on low
debug (fopcompiler), muffling scoping only behaved correctly at the
top level, which was basically an accident caused by the fact that
fopcompilation creates its own IR1-namespace, thereby passing separate
FREE-VARS tables around. Scoping was wrong because we were only doing
NOTE-UNDEFINED-REFERENCE once, as it was done in
FIND-FREE-VAR. Note undefined references in IR1-CONVERT-VAR, which
makes a bit more sense anyway, and fixes the issue.

Less easy to test but also fixed is the fact that we'd coalesce
warnings incorrectly, so that for example, on high debug,

(defun foo () x)

(defun bar () x)

would only warn once. The root cause and solution is the same.
This commit is contained in:
Charles Zhang 2022-02-18 22:33:33 -08:00
parent ef7597c7f6
commit d788babebf
4 changed files with 31 additions and 5 deletions

2
NEWS
View file

@ -9,6 +9,8 @@ changes relative to sbcl-2.2.1:
* enhancement: better source locations for structure accessors.
* bug fix: SB-COVER now always instruments top level forms correctly.
* bug fix: Muffling conditions now works correctly on higher debug settings.
* bug fix: Local muffling declarations now scope correctly with respect to
undefined variable warnings.
changes in sbcl-2.2.1 relative to sbcl-2.2.0:
* incompatible change: DEFINE-ALIEN-CALLBACK, which has never been exported

View file

@ -353,8 +353,6 @@
(type (info :variable :type name))
(where-from (info :variable :where-from name))
(deprecation-state (deprecated-thing-p 'variable name)))
(when (and (eq kind :unknown) (not deprecation-state))
(note-undefined-reference name :variable))
;; For deprecated vars, warn about LET and LAMBDA bindings, SETQ, and ref.
;; Don't warn again if the name was already seen by the transform
;; of SYMBOL[-GLOBAL]-VALUE.
@ -768,9 +766,14 @@
;; error (bug 412, lp#722734): checking for null RESULT is not enough,
;; since variables can become dead due to later optimizations.
(ir1-convert start next result
(if (eq (global-var-kind var) :global)
`(sym-global-val ',name)
`(symeval ',name)))
(case (global-var-kind var)
(:global `(sym-global-val ',name))
(:unknown
(when (not (deprecated-thing-p 'variable name))
(note-undefined-reference name :variable))
`(symeval ',name))
(t
`(symeval ',name))))
(etypecase var
(leaf
(cond

View file

@ -1036,6 +1036,10 @@ necessary, since type inference may take arbitrarily long to converge.")
;;; actually compile something. If (BLOCK-COMPILE *COMPILATION*) is T,
;;; then we still convert the form, but delay compilation, pushing the result
;;; on (TOPLEVEL-LAMBDAS *COMPILATION*) instead.
;;;
;;; The policy at this time becomes the default policy for compiling
;;; the form. Any enclosed PROCLAIMs will affect only subsequent
;;; forms.
(defun convert-and-maybe-compile (form path)
(declare (list path))
#+sb-xc-host

View file

@ -306,6 +306,23 @@ cat > $tmpfilename <<EOF
EOF
expect_failed_compile $tmpfilename
cat > $tmpfilename <<EOF
(declaim (optimize debug))
(locally
(declare (muffle-conditions warning))
(defun foo () x))
(defun bar () x)
EOF
expect_failed_compile $tmpfilename
cat > $tmpfilename <<EOF
(defun foo ()
(locally (declare (muffle-conditions warning))
(+ x x))
x)
EOF
expect_failed_compile $tmpfilename
# This should fail, and fail nicely -- not eg. loop trying to dump
# references to the unbound variable.
cat > $tmpfilename <<EOF