Fix private name mangling. The symtable also must do mangles so that

the scope of names can be correctly determined.
This commit is contained in:
Neil Schemenauer 2005-10-23 18:37:42 +00:00
parent 3a44aaa30f
commit 8b528b28f1
3 changed files with 47 additions and 19 deletions

View File

@ -17,7 +17,7 @@ struct symtable {
PyObject *st_stack; /* stack of namespace info */ PyObject *st_stack; /* stack of namespace info */
PyObject *st_global; /* borrowed ref to MODULE in st_symbols */ PyObject *st_global; /* borrowed ref to MODULE in st_symbols */
int st_nblocks; /* number of blocks */ int st_nblocks; /* number of blocks */
char *st_private; /* name of current class or NULL */ PyObject *st_private; /* name of current class or NULL */
int st_tmpname; /* temporary name counter */ int st_tmpname; /* temporary name counter */
PyFutureFeatures *st_future; /* module's future features */ PyFutureFeatures *st_future; /* module's future features */
}; };

View File

@ -2701,10 +2701,11 @@ inplace_binop(struct compiler *c, operator_ty op)
static int static int
compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx)
{ {
int op, scope; int op, scope, r, arg;
enum { OP_FAST, OP_GLOBAL, OP_DEREF, OP_NAME } optype; enum { OP_FAST, OP_GLOBAL, OP_DEREF, OP_NAME } optype;
PyObject *dict = c->u->u_names; PyObject *dict = c->u->u_names;
PyObject *mangled;
/* XXX AugStore isn't used anywhere! */ /* XXX AugStore isn't used anywhere! */
/* First check for assignment to __debug__. Param? */ /* First check for assignment to __debug__. Param? */
@ -2713,9 +2714,13 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx)
return compiler_error(c, "can not assign to __debug__"); return compiler_error(c, "can not assign to __debug__");
} }
mangled = _Py_Mangle(c->u->u_private, name);
if (!mangled)
return 0;
op = 0; op = 0;
optype = OP_NAME; optype = OP_NAME;
scope = PyST_GetScope(c->u->u_ste, name); scope = PyST_GetScope(c->u->u_ste, mangled);
switch (scope) { switch (scope) {
case FREE: case FREE:
dict = c->u->u_freevars; dict = c->u->u_freevars;
@ -2755,6 +2760,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx)
"can not delete variable '%s' referenced " "can not delete variable '%s' referenced "
"in nested scope", "in nested scope",
PyString_AS_STRING(name)); PyString_AS_STRING(name));
Py_DECREF(mangled);
return 0; return 0;
break; break;
case Param: case Param:
@ -2772,7 +2778,8 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx)
case Param: case Param:
assert(0); /* impossible */ assert(0); /* impossible */
} }
ADDOP_O(c, op, name, varnames); ADDOP_O(c, op, mangled, varnames);
Py_DECREF(mangled);
return 1; return 1;
case OP_GLOBAL: case OP_GLOBAL:
switch (ctx) { switch (ctx) {
@ -2801,7 +2808,12 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx)
} }
assert(op); assert(op);
return compiler_addop_name(c, op, dict, name); arg = compiler_add_o(c, dict, mangled);
if (arg < 0)
return 0;
r = compiler_addop_i(c, op, arg);
Py_DECREF(mangled);
return r;
} }
static int static int

View File

@ -740,8 +740,11 @@ static int
symtable_lookup(struct symtable *st, PyObject *name) symtable_lookup(struct symtable *st, PyObject *name)
{ {
PyObject *o; PyObject *o;
PyObject *mangled = _Py_Mangle(st->st_private, name);
o = PyDict_GetItem(st->st_cur->ste_symbols, name); if (!mangled)
return 0;
o = PyDict_GetItem(st->st_cur->ste_symbols, mangled);
Py_DECREF(mangled);
if (!o) if (!o)
return 0; return 0;
return PyInt_AsLong(o); return PyInt_AsLong(o);
@ -753,49 +756,57 @@ symtable_add_def(struct symtable *st, PyObject *name, int flag)
PyObject *o; PyObject *o;
PyObject *dict; PyObject *dict;
int val; int val;
PyObject *mangled = _Py_Mangle(st->st_private, name);
if (!mangled)
return 0;
dict = st->st_cur->ste_symbols; dict = st->st_cur->ste_symbols;
if ((o = PyDict_GetItem(dict, name))) { if ((o = PyDict_GetItem(dict, mangled))) {
val = PyInt_AS_LONG(o); val = PyInt_AS_LONG(o);
if ((flag & DEF_PARAM) && (val & DEF_PARAM)) { if ((flag & DEF_PARAM) && (val & DEF_PARAM)) {
/* Is it better to use 'mangled' or 'name' here? */
PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT, PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT,
PyString_AsString(name)); PyString_AsString(name));
PyErr_SyntaxLocation(st->st_filename, PyErr_SyntaxLocation(st->st_filename,
st->st_cur->ste_lineno); st->st_cur->ste_lineno);
return 0; goto error;
} }
val |= flag; val |= flag;
} else } else
val = flag; val = flag;
o = PyInt_FromLong(val); o = PyInt_FromLong(val);
if (o == NULL) if (o == NULL)
return 0; goto error;
if (PyDict_SetItem(dict, name, o) < 0) { if (PyDict_SetItem(dict, mangled, o) < 0) {
Py_DECREF(o); Py_DECREF(o);
return 0; goto error;
} }
Py_DECREF(o); Py_DECREF(o);
if (flag & DEF_PARAM) { if (flag & DEF_PARAM) {
if (PyList_Append(st->st_cur->ste_varnames, name) < 0) if (PyList_Append(st->st_cur->ste_varnames, mangled) < 0)
return 0; goto error;
} else if (flag & DEF_GLOBAL) { } else if (flag & DEF_GLOBAL) {
/* XXX need to update DEF_GLOBAL for other flags too; /* XXX need to update DEF_GLOBAL for other flags too;
perhaps only DEF_FREE_GLOBAL */ perhaps only DEF_FREE_GLOBAL */
val = flag; val = flag;
if ((o = PyDict_GetItem(st->st_global, name))) { if ((o = PyDict_GetItem(st->st_global, mangled))) {
val |= PyInt_AS_LONG(o); val |= PyInt_AS_LONG(o);
} }
o = PyInt_FromLong(val); o = PyInt_FromLong(val);
if (o == NULL) if (o == NULL)
return 0; goto error;
if (PyDict_SetItem(st->st_global, name, o) < 0) { if (PyDict_SetItem(st->st_global, mangled, o) < 0) {
Py_DECREF(o); Py_DECREF(o);
return 0; goto error;
} }
Py_DECREF(o); Py_DECREF(o);
} }
return 1; return 1;
error:
Py_DECREF(mangled);
return 0;
} }
/* VISIT, VISIT_SEQ and VIST_SEQ_TAIL take an ASDL type as their second argument. /* VISIT, VISIT_SEQ and VIST_SEQ_TAIL take an ASDL type as their second argument.
@ -849,17 +860,22 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
if (!symtable_exit_block(st, s)) if (!symtable_exit_block(st, s))
return 0; return 0;
break; break;
case ClassDef_kind: case ClassDef_kind: {
PyObject *tmp;
if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL)) if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL))
return 0; return 0;
VISIT_SEQ(st, expr, s->v.ClassDef.bases); VISIT_SEQ(st, expr, s->v.ClassDef.bases);
if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock,
(void *)s, s->lineno)) (void *)s, s->lineno))
return 0; return 0;
tmp = st->st_private;
st->st_private = s->v.ClassDef.name;
VISIT_SEQ(st, stmt, s->v.ClassDef.body); VISIT_SEQ(st, stmt, s->v.ClassDef.body);
st->st_private = tmp;
if (!symtable_exit_block(st, s)) if (!symtable_exit_block(st, s))
return 0; return 0;
break; break;
}
case Return_kind: case Return_kind:
if (s->v.Return.value) if (s->v.Return.value)
VISIT(st, expr, s->v.Return.value); VISIT(st, expr, s->v.Return.value);