summaryrefslogtreecommitdiffstats
path: root/Python/compile.c
diff options
context:
space:
mode:
authorJeremy Hylton <jeremy@alum.mit.edu>2003-07-15 20:23:26 (GMT)
committerJeremy Hylton <jeremy@alum.mit.edu>2003-07-15 20:23:26 (GMT)
commit1955fcf67aebb99c06715864de468a6be6ab9a6c (patch)
treee621ff2087b3c0e3306d423ef9d9f422990994f5 /Python/compile.c
parent35c38eaeae8d24fe0098f3942135b3ba28cffe85 (diff)
downloadcpython-1955fcf67aebb99c06715864de468a6be6ab9a6c.zip
cpython-1955fcf67aebb99c06715864de468a6be6ab9a6c.tar.gz
cpython-1955fcf67aebb99c06715864de468a6be6ab9a6c.tar.bz2
SF patch 763201: handling of SyntaxErrors in symbol table build
Fixes for three related bugs, including errors that caused a script to be ignored without printing an error message. The key problem was a bad interaction between syntax warnings and syntax errors. If an exception was already set when a warning was issued, the warning could clobber the exception. The PyErr_Occurred() check in issue_warning() isn't entirely satisfying (the caller should know whether there was already an error), but a better solution isn't immediately obvious. Bug fix candidate.
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c80
1 files changed, 47 insertions, 33 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 61b3c96..38624d4 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -686,7 +686,8 @@ static node *get_rawdocstring(node *);
static int get_ref_type(struct compiling *, char *);
/* symtable operations */
-static int symtable_build(struct compiling *, node *);
+static struct symtable *symtable_build(node *, PyFutureFeatures *,
+ const char *filename);
static int symtable_load_symbols(struct compiling *);
static struct symtable *symtable_init(void);
static void symtable_enter_scope(struct symtable *, char *, int, int);
@@ -4250,26 +4251,12 @@ PyNode_CompileSymtable(node *n, const char *filename)
ff = PyNode_Future(n, filename);
if (ff == NULL)
return NULL;
-
- st = symtable_init();
+ st = symtable_build(n, ff, filename);
if (st == NULL) {
PyObject_FREE((void *)ff);
return NULL;
}
- st->st_future = ff;
- symtable_enter_scope(st, TOP, TYPE(n), n->n_lineno);
- if (st->st_errors > 0)
- goto fail;
- symtable_node(st, n);
- if (st->st_errors > 0)
- goto fail;
-
return st;
- fail:
- PyObject_FREE((void *)ff);
- st->st_future = NULL;
- PySymtable_Free(st);
- return NULL;
}
static PyCodeObject *
@@ -4319,10 +4306,14 @@ jcompile(node *n, const char *filename, struct compiling *base,
sc.c_future->ff_features = merged;
flags->cf_flags = merged;
}
- if (symtable_build(&sc, n) < 0) {
+ sc.c_symtable = symtable_build(n, sc.c_future, sc.c_filename);
+ if (sc.c_symtable == NULL) {
com_free(&sc);
return NULL;
}
+ /* reset symbol table for second pass */
+ sc.c_symtable->st_nscopes = 1;
+ sc.c_symtable->st_pass = 2;
}
co = NULL;
if (symtable_load_symbols(&sc) < 0) {
@@ -4443,6 +4434,15 @@ get_ref_type(struct compiling *c, char *name)
static int
issue_warning(const char *msg, const char *filename, int lineno)
{
+ if (PyErr_Occurred()) {
+ /* This can happen because symtable_node continues
+ processing even after raising a SyntaxError.
+ Calling PyErr_WarnExplicit now would clobber the
+ pending exception; instead we fail and let that
+ exception propagate.
+ */
+ return -1;
+ }
if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, filename,
lineno, NULL, NULL) < 0) {
if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {
@@ -4466,23 +4466,37 @@ symtable_warn(struct symtable *st, char *msg)
/* Helper function for setting lineno and filename */
-static int
-symtable_build(struct compiling *c, node *n)
+static struct symtable *
+symtable_build(node *n, PyFutureFeatures *ff, const char *filename)
{
- if ((c->c_symtable = symtable_init()) == NULL)
- return -1;
- c->c_symtable->st_future = c->c_future;
- c->c_symtable->st_filename = c->c_filename;
- symtable_enter_scope(c->c_symtable, TOP, TYPE(n), n->n_lineno);
- if (c->c_symtable->st_errors > 0)
- return -1;
- symtable_node(c->c_symtable, n);
- if (c->c_symtable->st_errors > 0)
- return -1;
- /* reset for second pass */
- c->c_symtable->st_nscopes = 1;
- c->c_symtable->st_pass = 2;
- return 0;
+ struct symtable *st;
+
+ st = symtable_init();
+ if (st == NULL)
+ return NULL;
+ st->st_future = ff;
+ st->st_filename = filename;
+ symtable_enter_scope(st, TOP, TYPE(n), n->n_lineno);
+ if (st->st_errors > 0)
+ goto fail;
+ symtable_node(st, n);
+ if (st->st_errors > 0)
+ goto fail;
+ return st;
+ fail:
+ if (!PyErr_Occurred()) {
+ /* This could happen because after a syntax error is
+ detected, the symbol-table-building continues for
+ a while, and PyErr_Clear() might erroneously be
+ called during that process. One such case has been
+ fixed, but there might be more (now or later).
+ */
+ PyErr_SetString(PyExc_SystemError, "lost exception");
+ }
+ st->st_future = NULL;
+ st->st_filename = NULL;
+ PySymtable_Free(st);
+ return NULL;
}
static int