Commit e68140dd authored by Paul Prescod's avatar Paul Prescod

Better error message with UnboundLocalError

parent 408e9ae2
...@@ -73,7 +73,12 @@ static int exec_statement(PyFrameObject *, ...@@ -73,7 +73,12 @@ static int exec_statement(PyFrameObject *,
PyObject *, PyObject *, PyObject *); PyObject *, PyObject *, PyObject *);
static void set_exc_info(PyThreadState *, PyObject *, PyObject *, PyObject *); static void set_exc_info(PyThreadState *, PyObject *, PyObject *, PyObject *);
static void reset_exc_info(PyThreadState *); static void reset_exc_info(PyThreadState *);
static void format_exc_check_arg(PyObject *, char *, PyObject *);
#define NAME_ERROR_MSG \
"There is no variable named '%s'"
#define UNBOUNDLOCAL_ERROR_MSG \
"Local variable '%.200s' referenced before assignment"
/* Dynamic execution profile */ /* Dynamic execution profile */
#ifdef DYNAMIC_EXECUTION_PROFILE #ifdef DYNAMIC_EXECUTION_PROFILE
...@@ -1396,7 +1401,8 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -1396,7 +1401,8 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
break; break;
} }
if ((err = PyDict_DelItem(x, w)) != 0) if ((err = PyDict_DelItem(x, w)) != 0)
PyErr_SetObject(PyExc_NameError, w); format_exc_check_arg(PyExc_NameError,
NAME_ERROR_MSG ,w);
break; break;
case UNPACK_SEQUENCE: case UNPACK_SEQUENCE:
...@@ -1471,7 +1477,8 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -1471,7 +1477,8 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
case DELETE_GLOBAL: case DELETE_GLOBAL:
w = GETNAMEV(oparg); w = GETNAMEV(oparg);
if ((err = PyDict_DelItem(f->f_globals, w)) != 0) if ((err = PyDict_DelItem(f->f_globals, w)) != 0)
PyErr_SetObject(PyExc_NameError, w); format_exc_check_arg(
PyExc_NameError, NAME_ERROR_MSG ,w);
break; break;
case LOAD_CONST: case LOAD_CONST:
...@@ -1493,8 +1500,9 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -1493,8 +1500,9 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
if (x == NULL) { if (x == NULL) {
x = PyDict_GetItem(f->f_builtins, w); x = PyDict_GetItem(f->f_builtins, w);
if (x == NULL) { if (x == NULL) {
PyErr_SetObject( format_exc_check_arg(
PyExc_NameError, w); PyExc_NameError,
NAME_ERROR_MSG ,w);
break; break;
} }
} }
...@@ -1509,7 +1517,9 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -1509,7 +1517,9 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
if (x == NULL) { if (x == NULL) {
x = PyDict_GetItem(f->f_builtins, w); x = PyDict_GetItem(f->f_builtins, w);
if (x == NULL) { if (x == NULL) {
PyErr_SetObject(PyExc_NameError, w); format_exc_check_arg(
PyExc_NameError,
NAME_ERROR_MSG ,w);
break; break;
} }
} }
...@@ -1520,9 +1530,11 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -1520,9 +1530,11 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
case LOAD_FAST: case LOAD_FAST:
x = GETLOCAL(oparg); x = GETLOCAL(oparg);
if (x == NULL) { if (x == NULL) {
PyErr_SetObject(PyExc_UnboundLocalError, format_exc_check_arg(
PyTuple_GetItem(co->co_varnames, PyExc_UnboundLocalError,
oparg)); UNBOUNDLOCAL_ERROR_MSG,
PyTuple_GetItem(co->co_varnames, oparg)
);
break; break;
} }
Py_INCREF(x); Py_INCREF(x);
...@@ -1538,9 +1550,11 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -1538,9 +1550,11 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
case DELETE_FAST: case DELETE_FAST:
x = GETLOCAL(oparg); x = GETLOCAL(oparg);
if (x == NULL) { if (x == NULL) {
PyErr_SetObject(PyExc_UnboundLocalError, format_exc_check_arg(
PyTuple_GetItem(co->co_varnames, PyExc_UnboundLocalError,
oparg)); UNBOUNDLOCAL_ERROR_MSG,
PyTuple_GetItem(co->co_varnames, oparg)
);
break; break;
} }
SETLOCAL(oparg, NULL); SETLOCAL(oparg, NULL);
...@@ -3063,6 +3077,20 @@ exec_statement(PyFrameObject *f, PyObject *prog, PyObject *globals, ...@@ -3063,6 +3077,20 @@ exec_statement(PyFrameObject *f, PyObject *prog, PyObject *globals,
return 0; return 0;
} }
static void
format_exc_check_arg(PyObject *exc, char *format_str, PyObject *obj)
{
char *obj_str;
if (!obj)
return;
obj_str = PyString_AsString(obj);
if (!obj_str)
return;
PyErr_Format(exc, format_str, obj_str);
}
#ifdef DYNAMIC_EXECUTION_PROFILE #ifdef DYNAMIC_EXECUTION_PROFILE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment