From 2dfcdb848b2e9504227c6a86bc497a100808d125 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 14 Dec 2018 06:53:33 -0800 Subject: defvar: bugfix: bad state caused by exception. The following situation can occur: (defvar v expr) ;; expr throws! What happens is that the internal hash table of global variables ends up with an entry that has a nil value, instead of the expected (v . ) cons cell. The hash table entry is created when the table is probed for the existence of v, but then is never populated with a binding because expr throws. The consequence then is that (boundp v) returns nil, yet subsequent (defvar v ...) expressions think that v exists, and refuse to define it. (defparm v ...) also fails; it relies on (defvar ...) which fails to define the variable, and then tries to assign to it, which throws. * eval.c (rt_defvarl): If the hash table exists, but has a nil value, treat that as an undefined variable. Thus, define the variable not only if the hash cell is newly made, but also if it already exists, with a null cdr. --- eval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eval.c b/eval.c index 9cfeba03..2cf3e36e 100644 --- a/eval.c +++ b/eval.c @@ -1895,7 +1895,7 @@ static val rt_defvarl(val sym) val new_p; val cell = gethash_c(self, top_vb, sym, mkcloc(new_p)); - if (new_p) { + if (new_p || !cdr(cell)) { uw_purge_deferred_warning(cons(var_s, sym)); uw_purge_deferred_warning(cons(sym_s, sym)); remhash(top_smb, sym); -- cgit v1.2.3