bpo-28936: Detect lexically first syntax error first (#4097)

Lexically first global and nonlocal syntax errors at given scope should be detected first.
This commit is contained in:
Ivan Levkivskyi 2017-10-26 23:28:35 +02:00 committed by Serhiy Storchaka
parent 66c88ce30c
commit 8c83c23fa3
3 changed files with 45 additions and 27 deletions

View file

@ -9,6 +9,12 @@
#include "structmember.h"
/* error strings used for warnings */
#define GLOBAL_PARAM \
"name '%U' is parameter and global"
#define NONLOCAL_PARAM \
"name '%U' is parameter and nonlocal"
#define GLOBAL_AFTER_ASSIGN \
"name '%U' is assigned to before global declaration"
@ -465,12 +471,6 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
PyObject *global)
{
if (flags & DEF_GLOBAL) {
if (flags & DEF_PARAM) {
PyErr_Format(PyExc_SyntaxError,
"name '%U' is parameter and global",
name);
return error_at_directive(ste, name);
}
if (flags & DEF_NONLOCAL) {
PyErr_Format(PyExc_SyntaxError,
"name '%U' is nonlocal and global",
@ -485,12 +485,6 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
return 1;
}
if (flags & DEF_NONLOCAL) {
if (flags & DEF_PARAM) {
PyErr_Format(PyExc_SyntaxError,
"name '%U' is parameter and nonlocal",
name);
return error_at_directive(ste, name);
}
if (!bound) {
PyErr_Format(PyExc_SyntaxError,
"nonlocal declaration not allowed at module level");
@ -1284,9 +1278,11 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
long cur = symtable_lookup(st, name);
if (cur < 0)
VISIT_QUIT(st, 0);
if (cur & (DEF_LOCAL | USE | DEF_ANNOT)) {
char* msg;
if (cur & USE) {
if (cur & (DEF_PARAM | DEF_LOCAL | USE | DEF_ANNOT)) {
const char* msg;
if (cur & DEF_PARAM) {
msg = GLOBAL_PARAM;
} else if (cur & USE) {
msg = GLOBAL_AFTER_USE;
} else if (cur & DEF_ANNOT) {
msg = GLOBAL_ANNOT;
@ -1315,9 +1311,11 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
long cur = symtable_lookup(st, name);
if (cur < 0)
VISIT_QUIT(st, 0);
if (cur & (DEF_LOCAL | USE | DEF_ANNOT)) {
char* msg;
if (cur & USE) {
if (cur & (DEF_PARAM | DEF_LOCAL | USE | DEF_ANNOT)) {
const char* msg;
if (cur & DEF_PARAM) {
msg = NONLOCAL_PARAM;
} else if (cur & USE) {
msg = NONLOCAL_AFTER_USE;
} else if (cur & DEF_ANNOT) {
msg = NONLOCAL_ANNOT;