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:
parent
3a44aaa30f
commit
8b528b28f1
|
@ -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 */
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue