]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Fixup handling of free variables in methods when the class scope also
authorJeremy Hylton <jeremy@alum.mit.edu>
Tue, 20 Mar 2001 00:25:43 +0000 (00:25 +0000)
committerJeremy Hylton <jeremy@alum.mit.edu>
Tue, 20 Mar 2001 00:25:43 +0000 (00:25 +0000)
has a binding for the name.  The fix is in two places:

  - in symtable_update_free_vars, ignore a global stmt in a class scope
  - in symtable_load_symbols, add extra handling for names that are
    defined at class scope and free in a method

Closes SF bug 407800

Python/compile.c

index cec86695a862d1e14d0b05a37d18a00ff9416764..07729b1b3c27a93b7a90981a9e8d663b551d97e6 100644 (file)
@@ -3808,6 +3808,7 @@ dict_keys_inorder(PyObject *dict, int offset)
        while (PyDict_Next(dict, &pos, &k, &v)) {
                i = PyInt_AS_LONG(v);
                Py_INCREF(k);
+               assert((i - offset) < size);
                PyTuple_SET_ITEM(tuple, i - offset, k);
        }
        return tuple;
@@ -4316,9 +4317,17 @@ symtable_load_symbols(struct compiling *c)
                        /* undo the original DEF_FREE */
                        flags &= ~(DEF_FREE | DEF_FREE_CLASS);
 
-               if ((flags & (DEF_FREE | DEF_FREE_CLASS))
-                   && (flags & (DEF_LOCAL | DEF_PARAM)))
+               /* Deal with names that need two actions:
+                  1. Cell variables, which are also locals.
+                  2. Free variables in methods that are also class
+                  variables or declared global.
+               */
+               if (flags & (DEF_FREE | DEF_FREE_CLASS)) {
+                   if ((ste->ste_type == TYPE_CLASS 
+                        && flags != DEF_FREE_CLASS)
+                       || (flags & (DEF_LOCAL | DEF_PARAM)))
                        symtable_resolve_free(c, name, &si);
+               }
 
                if (flags & DEF_STAR) {
                        c->c_argcount--;
@@ -4478,7 +4487,7 @@ symtable_update_free_vars(struct symtable *st)
                           with bindings for N between B and A, then N
                           is global in B.
                        */
-                       if (v) {
+                       if (v && (ste->ste_type != TYPE_CLASS)) {
                                int flags = PyInt_AS_LONG(v); 
                                if (flags & DEF_GLOBAL) {
                                        symtable_undo_free(st, child->ste_id,