diff options
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ast.c | 35 | ||||
-rw-r--r-- | Python/bltinmodule.c | 69 | ||||
-rw-r--r-- | Python/compile.c | 64 | ||||
-rw-r--r-- | Python/mystrtoul.c | 64 | ||||
-rw-r--r-- | Python/peephole.c | 53 | ||||
-rw-r--r-- | Python/structmember.c | 42 | ||||
-rw-r--r-- | Python/symtable.c | 46 |
7 files changed, 207 insertions, 166 deletions
diff --git a/Python/ast.c b/Python/ast.c index b313ef2aa4..c611436f6d 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -376,10 +376,6 @@ set_context(expr_ty e, expr_context_ty ctx, const node *n) switch (e->kind) { case Attribute_kind: - if (ctx == Store && - !PyUnicode_CompareWithASCIIString(e->v.Attribute.attr, "None")) { - return ast_error(n, "assignment to None"); - } e->v.Attribute.ctx = ctx; break; case Subscript_kind: @@ -600,10 +596,6 @@ compiler_arg(struct compiling *c, const node *n) assert(TYPE(n) == tfpdef || TYPE(n) == vfpdef); ch = CHILD(n, 0); - if (!strcmp(STR(ch), "None")) { - ast_error(ch, "assignment to None"); - return NULL; - } name = NEW_IDENTIFIER(ch); if (!name) return NULL; @@ -641,10 +633,6 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start, case tfpdef: if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) { expression = ast_for_expr(c, CHILD(n, i + 2)); - if (!expression) { - ast_error(ch, "assignment to None"); - goto error; - } asdl_seq_SET(kwdefaults, j, expression); i += 2; /* '=' and test */ } @@ -663,10 +651,6 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start, annotation = NULL; } ch = CHILD(ch, 0); - if (!strcmp(STR(ch), "None")) { - ast_error(ch, "assignment to None"); - goto error; - } arg = arg(NEW_IDENTIFIER(ch), annotation, c->c_arena); if (!arg) { ast_error(ch, "expecting name"); @@ -817,10 +801,6 @@ ast_for_arguments(struct compiling *c, const node *n) if (res == -1) goto error; i = res; /* res has new position to process */ } - else if (!strcmp(STR(CHILD(ch, 0)), "None")) { - ast_error(CHILD(ch, 0), "assignment to None"); - goto error; - } else { vararg = NEW_IDENTIFIER(CHILD(ch, 0)); if (NCH(ch) > 1) { @@ -841,10 +821,6 @@ ast_for_arguments(struct compiling *c, const node *n) case DOUBLESTAR: ch = CHILD(n, i+1); /* tfpdef */ assert(TYPE(ch) == tfpdef || TYPE(ch) == vfpdef); - if (!strcmp(STR(CHILD(ch, 0)), "None")) { - ast_error(CHILD(ch, 0), "assignment to None"); - goto error; - } kwarg = NEW_IDENTIFIER(CHILD(ch, 0)); if (NCH(ch) > 1) { /* there is an annotation on the kwarg */ @@ -971,10 +947,6 @@ ast_for_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) name = NEW_IDENTIFIER(CHILD(n, name_i)); if (!name) return NULL; - else if (!strcmp(STR(CHILD(n, name_i)), "None")) { - ast_error(CHILD(n, name_i), "assignment to None"); - return NULL; - } args = ast_for_arguments(c, CHILD(n, name_i + 1)); if (!args) return NULL; @@ -2913,11 +2885,6 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) REQ(n, classdef); - if (!strcmp(STR(CHILD(n, 1)), "None")) { - ast_error(n, "assignment to None"); - return NULL; - } - if (NCH(n) == 4) { /* class NAME ':' suite */ s = ast_for_suite(c, CHILD(n, 3)); if (!s) @@ -3039,8 +3006,6 @@ parsenumber(const char *s) #ifndef WITHOUT_COMPLEX imflag = *end == 'j' || *end == 'J'; #endif - if (*end == 'l' || *end == 'L') - return PyLong_FromString((char *)s, (char **)0, 0); if (s[0] == '0') { x = (long) PyOS_strtoul((char *)s, (char **)&end, 0); if (x < 0 && errno == 0) { diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 3b43ff953a..a2e48b1d9c 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -31,7 +31,8 @@ static PyObject *filtertuple (PyObject *, PyObject *); static PyObject * builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) { - PyObject *func, *name, *bases, *mkw, *meta, *prep, *ns, *res; + PyObject *func, *name, *bases, *mkw, *meta, *prep, *ns, *cell; + PyObject *cls = NULL; Py_ssize_t nargs, nbases; assert(args != NULL); @@ -112,22 +113,25 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } } - res = PyObject_CallFunctionObjArgs(func, ns, NULL); - if (res != NULL) { + cell = PyObject_CallFunctionObjArgs(func, ns, NULL); + if (cell != NULL) { PyObject *margs; - Py_DECREF(res); - res = NULL; margs = Py_BuildValue("OOO", name, bases, ns); if (margs != NULL) { - res = PyEval_CallObjectWithKeywords(meta, margs, mkw); + cls = PyEval_CallObjectWithKeywords(meta, margs, mkw); Py_DECREF(margs); } + if (cls != NULL && PyCell_Check(cell)) { + Py_INCREF(cls); + PyCell_SET(cell, cls); + } + Py_DECREF(cell); } Py_DECREF(ns); Py_DECREF(meta); Py_XDECREF(mkw); Py_DECREF(bases); - return res; + return cls; } PyDoc_STRVAR(build_class_doc, @@ -245,6 +249,18 @@ Return True if bool(x) is True for any x in the iterable."); static PyObject * +builtin_bin(PyObject *self, PyObject *v) +{ + return PyNumber_ToBase(v, 2); +} + +PyDoc_STRVAR(bin_doc, +"bin(number) -> string\n\ +\n\ +Return the binary representation of an integer or long integer."); + + +static PyObject * builtin_filter(PyObject *self, PyObject *args) { PyObject *func, *seq, *result, *it, *arg; @@ -1192,24 +1208,7 @@ the same hash value. The reverse is not necessarily true, but likely."); static PyObject * builtin_hex(PyObject *self, PyObject *v) { - PyNumberMethods *nb; - PyObject *res; - - if ((nb = v->ob_type->tp_as_number) == NULL || - nb->nb_hex == NULL) { - PyErr_SetString(PyExc_TypeError, - "hex() argument can't be converted to hex"); - return NULL; - } - res = (*nb->nb_hex)(v); - if (res && !PyString_Check(res) && !PyUnicode_Check(res)) { - PyErr_Format(PyExc_TypeError, - "__hex__ returned non-string (type %.200s)", - res->ob_type->tp_name); - Py_DECREF(res); - return NULL; - } - return res; + return PyNumber_ToBase(v, 16); } PyDoc_STRVAR(hex_doc, @@ -1392,24 +1391,7 @@ With two or more arguments, return the largest argument."); static PyObject * builtin_oct(PyObject *self, PyObject *v) { - PyNumberMethods *nb; - PyObject *res; - - if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL || - nb->nb_oct == NULL) { - PyErr_SetString(PyExc_TypeError, - "oct() argument can't be converted to oct"); - return NULL; - } - res = (*nb->nb_oct)(v); - if (res && !PyString_Check(res) && !PyUnicode_Check(res)) { - PyErr_Format(PyExc_TypeError, - "__oct__ returned non-string (type %.200s)", - res->ob_type->tp_name); - Py_DECREF(res); - return NULL; - } - return res; + return PyNumber_ToBase(v, 8); } PyDoc_STRVAR(oct_doc, @@ -1949,6 +1931,7 @@ static PyMethodDef builtin_methods[] = { {"abs", builtin_abs, METH_O, abs_doc}, {"all", builtin_all, METH_O, all_doc}, {"any", builtin_any, METH_O, any_doc}, + {"bin", builtin_bin, METH_O, bin_doc}, {"chr", builtin_chr, METH_VARARGS, chr_doc}, {"chr8", builtin_chr8, METH_VARARGS, chr8_doc}, {"cmp", builtin_cmp, METH_VARARGS, cmp_doc}, diff --git a/Python/compile.c b/Python/compile.c index fde4591cf3..0f5fd2dfde 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -373,10 +373,12 @@ dictbytype(PyObject *src, int scope_type, int flag, int offset) while (PyDict_Next(src, &pos, &k, &v)) { /* XXX this should probably be a macro in symtable.h */ + long vi; assert(PyInt_Check(v)); - scope = (PyInt_AS_LONG(v) >> SCOPE_OFFSET) & SCOPE_MASK; + vi = PyInt_AS_LONG(v); + scope = (vi >> SCOPE_OFFSET) & SCOPE_MASK; - if (scope == scope_type || PyInt_AS_LONG(v) & flag) { + if (scope == scope_type || vi & flag) { PyObject *tuple, *item = PyInt_FromLong(i); if (item == NULL) { Py_DECREF(dest); @@ -1125,7 +1127,8 @@ compiler_body(struct compiler *c, asdl_seq *stmts) if (!asdl_seq_LEN(stmts)) return 1; st = (stmt_ty)asdl_seq_GET(stmts, 0); - if (compiler_isdocstring(st)) { + if (compiler_isdocstring(st) && Py_OptimizeFlag < 2) { + /* don't generate docstrings if -OO */ i = 1; VISIT(c, expr, st->v.Expr.value); if (!compiler_nameop(c, __doc__, Store)) @@ -1251,7 +1254,8 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, int args) else /* (reftype == FREE) */ arg = compiler_lookup_arg(c->u->u_freevars, name); if (arg == -1) { - printf("lookup %s in %s %d %d\n" + fprintf(stderr, + "lookup %s in %s %d %d\n" "freevars of %s: %s\n", PyObject_REPR(name), PyString_AS_STRING(c->u->u_name), @@ -1474,7 +1478,6 @@ compiler_function(struct compiler *c, stmt_ty s) static int compiler_class(struct compiler *c, stmt_ty s) { - static PyObject *build_class = NULL; static PyObject *locals = NULL; PyCodeObject *co; PyObject *str; @@ -1485,13 +1488,7 @@ compiler_class(struct compiler *c, stmt_ty s) if (!compiler_decorators(c, decos)) return 0; - /* initialize statics */ - if (build_class == NULL) { - build_class = PyUnicode_FromString("__build_class__"); - if (build_class == NULL) - return 0; - } if (locals == NULL) { locals = PyUnicode_FromString("__locals__"); if (locals == NULL) @@ -1501,14 +1498,16 @@ compiler_class(struct compiler *c, stmt_ty s) /* ultimately generate code for: <name> = __build_class__(<func>, <name>, *<bases>, **<keywords>) where: - <func> is a function/closure created from the class body + <func> is a function/closure created from the class body; + it has a single argument (__locals__) where the dict + (or MutableSequence) representing the locals is passed <name> is the class name <bases> is the positional arguments and *varargs argument <keywords> is the keyword arguments and **kwds argument This borrows from compiler_call. */ - /* 0. Create a fake variable named __locals__ */ + /* 0. Create a fake argument named __locals__ */ ste = PySymtable_Lookup(c->c_st, s); if (ste == NULL) return 0; @@ -1528,11 +1527,11 @@ compiler_class(struct compiler *c, stmt_ty s) c->u->u_private = s->v.ClassDef.name; /* force it to have one mandatory argument */ c->u->u_argcount = 1; - /* load the first argument ... */ + /* load the first argument (__locals__) ... */ ADDOP_I(c, LOAD_FAST, 0); /* ... and store it into f_locals */ ADDOP_IN_SCOPE(c, STORE_LOCALS); - /* load __name__ ... */ + /* load (global) __name__ ... */ str = PyUnicode_InternFromString("__name__"); if (!str || !compiler_nameop(c, str, Load)) { Py_XDECREF(str); @@ -1553,8 +1552,24 @@ compiler_class(struct compiler *c, stmt_ty s) compiler_exit_scope(c); return 0; } - /* return None */ - ADDOP_O(c, LOAD_CONST, Py_None, consts); + /* return the (empty) __class__ cell */ + str = PyUnicode_InternFromString("__class__"); + if (str == NULL) { + compiler_exit_scope(c); + return 0; + } + i = compiler_lookup_arg(c->u->u_cellvars, str); + Py_DECREF(str); + if (i == -1) { + /* This happens when nobody references the cell */ + PyErr_Clear(); + /* Return None */ + ADDOP_O(c, LOAD_CONST, Py_None, consts); + } + else { + /* Return the cell where to store __class__ */ + ADDOP_I(c, LOAD_CLOSURE, i); + } ADDOP_IN_SCOPE(c, RETURN_VALUE); /* create the code object */ co = assemble(c, 1); @@ -2421,7 +2436,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) return compiler_error(c, "can not assign to __debug__"); } -mangled = _Py_Mangle(c->u->u_private, name); + mangled = _Py_Mangle(c->u->u_private, name); if (!mangled) return 0; @@ -2947,6 +2962,7 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k) static int expr_constant(expr_ty e) { + char *id; switch (e->kind) { case Ellipsis_kind: return 1; @@ -2955,11 +2971,13 @@ expr_constant(expr_ty e) case Str_kind: return PyObject_IsTrue(e->v.Str.s); case Name_kind: - /* __debug__ is not assignable, so we can optimize - * it away in if and while statements */ - if (PyUnicode_CompareWithASCIIString(e->v.Name.id, - "__debug__") == 0) - return ! Py_OptimizeFlag; + /* optimize away names that can't be reassigned */ + id = _PyUnicode_AsDefaultEncodedString(e->v.Name.id, NULL); + if (strcmp(id, "True") == 0) return 1; + if (strcmp(id, "False") == 0) return 0; + if (strcmp(id, "None") == 0) return 0; + if (strcmp(id, "__debug__") == 0) + return ! Py_OptimizeFlag; /* fall through */ default: return -1; diff --git a/Python/mystrtoul.c b/Python/mystrtoul.c index f0070575db..cf23051a43 100644 --- a/Python/mystrtoul.c +++ b/Python/mystrtoul.c @@ -91,7 +91,7 @@ static int digitlimit[] = { ** This is a general purpose routine for converting ** an ascii string to an integer in an arbitrary base. ** Leading white space is ignored. If 'base' is zero -** it looks for a leading 0, 0x or 0X to tell which +** it looks for a leading 0b, 0o or 0x to tell which ** base. If these are absent it defaults to 10. ** Base must be 0 or between 2 and 36 (inclusive). ** If 'ptr' is non-NULL it will contain a pointer to @@ -110,29 +110,57 @@ PyOS_strtoul(register char *str, char **ptr, int base) while (*str && isspace(Py_CHARMASK(*str))) ++str; - /* check for leading 0 or 0x for auto-base or base 16 */ + /* check for leading 0b, 0o or 0x for auto-base or base 16 */ switch (base) { - case 0: /* look for leading 0, 0x or 0X */ - if (*str == '0') { + case 0: /* look for leading 0b, 0o or 0x */ + if (*str == '0') { + ++str; + if (*str == 'x' || *str == 'X') { + ++str; + base = 16; + } else if (*str == 'o' || *str == 'O') { ++str; - if (*str == 'x' || *str == 'X') { + base = 8; + } else if (*str == 'b' || *str == 'B') { + ++str; + base = 2; + } else { + /* skip all zeroes... */ + while (*str == '0') + ++str; + while (isspace(Py_CHARMASK(*str))) ++str; - base = 16; - } - else - base = 8; + if (ptr) + *ptr = str; + return 0; } - else - base = 10; - break; + } + else + base = 10; + break; - case 16: /* skip leading 0x or 0X */ - if (*str == '0') { + /* even with explicit base, skip leading 0? prefix */ + case 16: + if (*str == '0') { + ++str; + if (*str == 'x' || *str == 'X') ++str; - if (*str == 'x' || *str == 'X') - ++str; - } - break; + } + break; + case 8: + if (*str == '0') { + ++str; + if (*str == 'o' || *str == 'O') + ++str; + } + break; + case 2: + if(*str == '0') { + ++str; + if (*str == 'b' || *str == 'B') + ++str; + } + break; } /* catch silly bases */ diff --git a/Python/peephole.c b/Python/peephole.c index 7c4640cac7..d012d391e7 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -257,6 +257,37 @@ markblocks(unsigned char *code, int len) return blocks; } +/* Helper to replace LOAD_NAME None/True/False with LOAD_CONST + Returns: 0 if no change, 1 if change, -1 if error */ +static int +load_global(unsigned char *codestr, Py_ssize_t i, char *name, PyObject *consts) +{ + Py_ssize_t j; + PyObject *obj; + if (name == NULL) + return 0; + if (strcmp(name, "None") == 0) + obj = Py_None; + else if (strcmp(name, "True") == 0) + obj = Py_True; + else if (strcmp(name, "False") == 0) + obj = Py_False; + else + return 0; + for (j = 0; j < PyList_GET_SIZE(consts); j++) { + if (PyList_GET_ITEM(consts, j) == obj) + break; + } + if (j == PyList_GET_SIZE(consts)) { + if (PyList_Append(consts, obj) < 0) + return -1; + } + assert(PyList_GET_ITEM(consts, j) == obj); + codestr[i] = LOAD_CONST; + SETARG(codestr, i, j); + return 1; +} + /* Perform basic peephole optimizations to components of a code object. The consts object should still be in list form to allow new constants to be appended. @@ -302,7 +333,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, /* Avoid situations where jump retargeting could overflow */ assert(PyString_Check(code)); - codelen = PyString_Size(code); + codelen = PyString_GET_SIZE(code); if (codelen > 32700) goto exitUnchanged; @@ -371,25 +402,17 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, codestr[i+3] = NOP; break; - /* Replace LOAD_GLOBAL/LOAD_NAME None - with LOAD_CONST None */ + /* Replace LOAD_GLOBAL/LOAD_NAME None/True/False + with LOAD_CONST None/True/False */ case LOAD_NAME: case LOAD_GLOBAL: j = GETARG(codestr, i); name = PyString_AsString(PyTuple_GET_ITEM(names, j)); - if (name == NULL || strcmp(name, "None") != 0) + h = load_global(codestr, i, name, consts); + if (h < 0) + goto exitUnchanged; + else if (h == 0) continue; - for (j=0 ; j < PyList_GET_SIZE(consts) ; j++) { - if (PyList_GET_ITEM(consts, j) == Py_None) - break; - } - if (j == PyList_GET_SIZE(consts)) { - if (PyList_Append(consts, Py_None) == -1) - goto exitUnchanged; - } - assert(PyList_GET_ITEM(consts, j) == Py_None); - codestr[i] = LOAD_CONST; - SETARG(codestr, i, j); cumlc = lastlc + 1; break; diff --git a/Python/structmember.c b/Python/structmember.c index b6cf2ac17b..1de223850c 100644 --- a/Python/structmember.c +++ b/Python/structmember.c @@ -289,31 +289,25 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) } break; #ifdef HAVE_LONG_LONG - case T_LONGLONG: - if (!PyLong_Check(v)) { - PyErr_BadArgument(); + case T_LONGLONG:{ + PY_LONG_LONG value; + *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v); + if ((value == -1) && PyErr_Occurred()) return -1; - } else { - PY_LONG_LONG value; - *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v); - if ((value == -1) && PyErr_Occurred()) { - return -1; - } - } - break; - case T_ULONGLONG: - if (!PyLong_Check(v)) { - PyErr_BadArgument(); - return -1; - } else { - unsigned PY_LONG_LONG value; - *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v); - if ((value == (unsigned PY_LONG_LONG)-1) && - PyErr_Occurred()) { - return -1; - } - } - break; + break; + } + case T_ULONGLONG:{ + unsigned PY_LONG_LONG value; + /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong + doesn't ??? */ + if (PyLong_Check(v)) + *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v); + else + *(unsigned PY_LONG_LONG*)addr = value = PyInt_AsLong(v); + if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred()) + return -1; + break; + } #endif /* HAVE_LONG_LONG */ default: PyErr_Format(PyExc_SystemError, diff --git a/Python/symtable.c b/Python/symtable.c index 68c182133a..30e97d6f5a 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -183,7 +183,7 @@ static int symtable_visit_annotations(struct symtable *st, stmt_ty s); static identifier top = NULL, lambda = NULL, genexpr = NULL, - listcomp = NULL, setcomp = NULL; + listcomp = NULL, setcomp = NULL, __class__ = NULL; #define GET_IDENTIFIER(VAR) \ ((VAR) ? (VAR) : ((VAR) = PyUnicode_InternFromString(# VAR))) @@ -317,7 +317,7 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name) /* Analyze raw symbol information to determine scope of each name. - The next several functions are helpers for PySymtable_Analyze(), + The next several functions are helpers for symtable_analyze(), which determines whether a name is local, global, or free. In addition, it determines which local variables are cell variables; they provide bindings that are used for free variables in enclosed blocks. @@ -464,10 +464,13 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, Note that the current block's free variables are included in free. That's safe because no name can be free and local in the same scope. + + The 'restrict' argument may be set to a string to restrict the analysis + to the one variable whose name equals that string (e.g. "__class__"). */ static int -analyze_cells(PyObject *scopes, PyObject *free) +analyze_cells(PyObject *scopes, PyObject *free, const char *restrict) { PyObject *name, *v, *v_cell; int success = 0; @@ -484,6 +487,9 @@ analyze_cells(PyObject *scopes, PyObject *free) continue; if (!PySet_Contains(free, name)) continue; + if (restrict != NULL && + PyUnicode_CompareWithASCIIString(name, restrict)) + continue; /* Replace LOCAL with CELL for this name, and remove from free. It is safe to replace the value of name in the dict, because it will not cause a resize. @@ -589,7 +595,7 @@ update_symbols(PyObject *symbols, PyObject *scopes, } Py_DECREF(v_new); } - /* It's a cell, or already a free variable in this scope */ + /* It's a cell, or already free in this scope */ Py_DECREF(name); continue; } @@ -675,8 +681,7 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, goto error; } - /* Populate global and bound sets to be passed to children. - */ + /* Populate global and bound sets to be passed to children. */ if (ste->ste_type != ClassBlock) { /* Add function locals to bound set */ if (ste->ste_type == FunctionBlock) { @@ -695,6 +700,14 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, goto error; Py_DECREF(newglobal); } + else { + /* Special-case __class__ */ + if (!GET_IDENTIFIER(__class__)) + goto error; + assert(PySet_Contains(local, __class__) == 1); + if (PySet_Add(newbound, __class__) < 0) + goto error; + } /* Recursively call analyze_block() on each child block */ for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) { @@ -709,8 +722,12 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, ste->ste_child_free = 1; } - /* Check if any local variables need to be converted to cell variables */ - if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree)) + /* Check if any local variables must be converted to cell variables */ + if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree, + NULL)) + goto error; + else if (ste->ste_type == ClassBlock && !analyze_cells(scopes, newfree, + "__class__")) goto error; /* Records the results of the analysis in the symbol table entry */ if (!update_symbols(ste->ste_symbols, scopes, bound, newfree, @@ -1027,6 +1044,11 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, (void *)s, s->lineno)) return 0; + if (!GET_IDENTIFIER(__class__) || + !symtable_add_def(st, __class__, DEF_LOCAL)) { + symtable_exit_block(st, s); + return 0; + } tmp = st->st_private; st->st_private = s->v.ClassDef.name; VISIT_SEQ_IN_BLOCK(st, stmt, s->v.ClassDef.body, s); @@ -1294,6 +1316,14 @@ symtable_visit_expr(struct symtable *st, expr_ty e) if (!symtable_add_def(st, e->v.Name.id, e->v.Name.ctx == Load ? USE : DEF_LOCAL)) return 0; + /* Special-case super: it counts as a use of __class__ */ + if (e->v.Name.ctx == Load && + st->st_cur->ste_type == FunctionBlock && + !PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) { + if (!GET_IDENTIFIER(__class__) || + !symtable_add_def(st, __class__, USE)) + return 0; + } break; /* child nodes of List and Tuple will have expr_context set */ case List_kind: |