diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2001-03-20 00:25:43 (GMT) |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2001-03-20 00:25:43 (GMT) |
commit | ce7ef599d2df7c43f8228f22a77de4554039dc0f (patch) | |
tree | 448f981095e78aa66180a78910a2a9c1b9e13ce0 /Python | |
parent | e241e29f3d0c4a2e4c7beee018ae409beb4239de (diff) | |
download | cpython-ce7ef599d2df7c43f8228f22a77de4554039dc0f.zip cpython-ce7ef599d2df7c43f8228f22a77de4554039dc0f.tar.gz cpython-ce7ef599d2df7c43f8228f22a77de4554039dc0f.tar.bz2 |
Fixup handling of free variables in methods when the class scope also
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
Diffstat (limited to 'Python')
-rw-r--r-- | Python/compile.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/Python/compile.c b/Python/compile.c index cec8669..07729b1 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -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, |