mirror of
https://github.com/python/cpython.git
synced 2024-11-23 01:45:25 +08:00
gh-122313: Clean up deep recursion guarding code in the compiler (GH-122640)
Add ENTER_RECURSIVE and LEAVE_RECURSIVE macros in ast.c, ast_opt.c and symtable.c. Remove VISIT_QUIT macro in symtable.c. The current recursion depth counter only needs to be updated during normal execution -- all functions should just return an error code if an error occurs.
This commit is contained in:
parent
fe0a28d850
commit
efcd65cd84
46
Python/ast.c
46
Python/ast.c
@ -14,6 +14,20 @@ struct validator {
|
||||
int recursion_limit; /* recursion limit */
|
||||
};
|
||||
|
||||
#define ENTER_RECURSIVE(ST) \
|
||||
do { \
|
||||
if (++(ST)->recursion_depth > (ST)->recursion_limit) { \
|
||||
PyErr_SetString(PyExc_RecursionError, \
|
||||
"maximum recursion depth exceeded during compilation"); \
|
||||
return 0; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LEAVE_RECURSIVE(ST) \
|
||||
do { \
|
||||
--(ST)->recursion_depth; \
|
||||
} while(0)
|
||||
|
||||
static int validate_stmts(struct validator *, asdl_stmt_seq *);
|
||||
static int validate_exprs(struct validator *, asdl_expr_seq *, expr_context_ty, int);
|
||||
static int validate_patterns(struct validator *, asdl_pattern_seq *, int);
|
||||
@ -166,11 +180,7 @@ validate_constant(struct validator *state, PyObject *value)
|
||||
return 1;
|
||||
|
||||
if (PyTuple_CheckExact(value) || PyFrozenSet_CheckExact(value)) {
|
||||
if (++state->recursion_depth > state->recursion_limit) {
|
||||
PyErr_SetString(PyExc_RecursionError,
|
||||
"maximum recursion depth exceeded during compilation");
|
||||
return 0;
|
||||
}
|
||||
ENTER_RECURSIVE(state);
|
||||
|
||||
PyObject *it = PyObject_GetIter(value);
|
||||
if (it == NULL)
|
||||
@ -195,7 +205,7 @@ validate_constant(struct validator *state, PyObject *value)
|
||||
}
|
||||
|
||||
Py_DECREF(it);
|
||||
--state->recursion_depth;
|
||||
LEAVE_RECURSIVE(state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -213,11 +223,7 @@ validate_expr(struct validator *state, expr_ty exp, expr_context_ty ctx)
|
||||
assert(!PyErr_Occurred());
|
||||
VALIDATE_POSITIONS(exp);
|
||||
int ret = -1;
|
||||
if (++state->recursion_depth > state->recursion_limit) {
|
||||
PyErr_SetString(PyExc_RecursionError,
|
||||
"maximum recursion depth exceeded during compilation");
|
||||
return 0;
|
||||
}
|
||||
ENTER_RECURSIVE(state);
|
||||
int check_ctx = 1;
|
||||
expr_context_ty actual_ctx;
|
||||
|
||||
@ -398,7 +404,7 @@ validate_expr(struct validator *state, expr_ty exp, expr_context_ty ctx)
|
||||
PyErr_SetString(PyExc_SystemError, "unexpected expression");
|
||||
ret = 0;
|
||||
}
|
||||
state->recursion_depth--;
|
||||
LEAVE_RECURSIVE(state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -544,11 +550,7 @@ validate_pattern(struct validator *state, pattern_ty p, int star_ok)
|
||||
assert(!PyErr_Occurred());
|
||||
VALIDATE_POSITIONS(p);
|
||||
int ret = -1;
|
||||
if (++state->recursion_depth > state->recursion_limit) {
|
||||
PyErr_SetString(PyExc_RecursionError,
|
||||
"maximum recursion depth exceeded during compilation");
|
||||
return 0;
|
||||
}
|
||||
ENTER_RECURSIVE(state);
|
||||
switch (p->kind) {
|
||||
case MatchValue_kind:
|
||||
ret = validate_pattern_match_value(state, p->v.MatchValue.value);
|
||||
@ -690,7 +692,7 @@ validate_pattern(struct validator *state, pattern_ty p, int star_ok)
|
||||
PyErr_SetString(PyExc_SystemError, "unexpected pattern");
|
||||
ret = 0;
|
||||
}
|
||||
state->recursion_depth--;
|
||||
LEAVE_RECURSIVE(state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -725,11 +727,7 @@ validate_stmt(struct validator *state, stmt_ty stmt)
|
||||
assert(!PyErr_Occurred());
|
||||
VALIDATE_POSITIONS(stmt);
|
||||
int ret = -1;
|
||||
if (++state->recursion_depth > state->recursion_limit) {
|
||||
PyErr_SetString(PyExc_RecursionError,
|
||||
"maximum recursion depth exceeded during compilation");
|
||||
return 0;
|
||||
}
|
||||
ENTER_RECURSIVE(state);
|
||||
switch (stmt->kind) {
|
||||
case FunctionDef_kind:
|
||||
ret = validate_body(state, stmt->v.FunctionDef.body, "FunctionDef") &&
|
||||
@ -946,7 +944,7 @@ validate_stmt(struct validator *state, stmt_ty stmt)
|
||||
PyErr_SetString(PyExc_SystemError, "unexpected statement");
|
||||
ret = 0;
|
||||
}
|
||||
state->recursion_depth--;
|
||||
LEAVE_RECURSIVE(state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,19 @@ typedef struct {
|
||||
int recursion_limit; /* recursion limit */
|
||||
} _PyASTOptimizeState;
|
||||
|
||||
#define ENTER_RECURSIVE(ST) \
|
||||
do { \
|
||||
if (++(ST)->recursion_depth > (ST)->recursion_limit) { \
|
||||
PyErr_SetString(PyExc_RecursionError, \
|
||||
"maximum recursion depth exceeded during compilation"); \
|
||||
return 0; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LEAVE_RECURSIVE(ST) \
|
||||
do { \
|
||||
--(ST)->recursion_depth; \
|
||||
} while(0)
|
||||
|
||||
static int
|
||||
make_const(expr_ty node, PyObject *val, PyArena *arena)
|
||||
@ -708,11 +721,7 @@ astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
|
||||
static int
|
||||
astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
|
||||
{
|
||||
if (++state->recursion_depth > state->recursion_limit) {
|
||||
PyErr_SetString(PyExc_RecursionError,
|
||||
"maximum recursion depth exceeded during compilation");
|
||||
return 0;
|
||||
}
|
||||
ENTER_RECURSIVE(state);
|
||||
switch (node_->kind) {
|
||||
case BoolOp_kind:
|
||||
CALL_SEQ(astfold_expr, expr, node_->v.BoolOp.values);
|
||||
@ -811,7 +820,7 @@ astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
|
||||
case Name_kind:
|
||||
if (node_->v.Name.ctx == Load &&
|
||||
_PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
|
||||
state->recursion_depth--;
|
||||
LEAVE_RECURSIVE(state);
|
||||
return make_const(node_, PyBool_FromLong(!state->optimize), ctx_);
|
||||
}
|
||||
break;
|
||||
@ -824,7 +833,7 @@ astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
|
||||
// No default case, so the compiler will emit a warning if new expression
|
||||
// kinds are added without being handled here
|
||||
}
|
||||
state->recursion_depth--;
|
||||
LEAVE_RECURSIVE(state);;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -871,11 +880,7 @@ astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
|
||||
static int
|
||||
astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
|
||||
{
|
||||
if (++state->recursion_depth > state->recursion_limit) {
|
||||
PyErr_SetString(PyExc_RecursionError,
|
||||
"maximum recursion depth exceeded during compilation");
|
||||
return 0;
|
||||
}
|
||||
ENTER_RECURSIVE(state);
|
||||
switch (node_->kind) {
|
||||
case FunctionDef_kind:
|
||||
CALL_SEQ(astfold_type_param, type_param, node_->v.FunctionDef.type_params);
|
||||
@ -999,7 +1004,7 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
|
||||
// No default case, so the compiler will emit a warning if new statement
|
||||
// kinds are added without being handled here
|
||||
}
|
||||
state->recursion_depth--;
|
||||
LEAVE_RECURSIVE(state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1031,11 +1036,7 @@ astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
|
||||
// Currently, this is really only used to form complex/negative numeric
|
||||
// constants in MatchValue and MatchMapping nodes
|
||||
// We still recurse into all subexpressions and subpatterns anyway
|
||||
if (++state->recursion_depth > state->recursion_limit) {
|
||||
PyErr_SetString(PyExc_RecursionError,
|
||||
"maximum recursion depth exceeded during compilation");
|
||||
return 0;
|
||||
}
|
||||
ENTER_RECURSIVE(state);
|
||||
switch (node_->kind) {
|
||||
case MatchValue_kind:
|
||||
CALL(astfold_expr, expr_ty, node_->v.MatchValue.value);
|
||||
@ -1067,7 +1068,7 @@ astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
|
||||
// No default case, so the compiler will emit a warning if new pattern
|
||||
// kinds are added without being handled here
|
||||
}
|
||||
state->recursion_depth--;
|
||||
LEAVE_RECURSIVE(state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1617,17 +1617,17 @@ symtable_enter_type_param_block(struct symtable *st, identifier name,
|
||||
VISIT_SEQ_TAIL permits the start of an ASDL sequence to be skipped, which is
|
||||
useful if the first node in the sequence requires special treatment.
|
||||
|
||||
VISIT_QUIT macro returns the specified value exiting from the function but
|
||||
first adjusts current recursion counter depth.
|
||||
*/
|
||||
ENTER_RECURSIVE macro increments the current recursion depth counter.
|
||||
It should be used at the beginning of the recursive function.
|
||||
|
||||
#define VISIT_QUIT(ST, X) \
|
||||
return --(ST)->recursion_depth,(X)
|
||||
LEAVE_RECURSIVE macro decrements the current recursion depth counter.
|
||||
It should be used at the end of the recursive function.
|
||||
*/
|
||||
|
||||
#define VISIT(ST, TYPE, V) \
|
||||
do { \
|
||||
if (!symtable_visit_ ## TYPE((ST), (V))) { \
|
||||
VISIT_QUIT((ST), 0); \
|
||||
return 0; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
@ -1638,7 +1638,7 @@ symtable_enter_type_param_block(struct symtable *st, identifier name,
|
||||
for (i = 0; i < asdl_seq_LEN(seq); i++) { \
|
||||
TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \
|
||||
if (!symtable_visit_ ## TYPE((ST), elt)) \
|
||||
VISIT_QUIT((ST), 0); \
|
||||
return 0; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
@ -1649,7 +1649,7 @@ symtable_enter_type_param_block(struct symtable *st, identifier name,
|
||||
for (i = (START); i < asdl_seq_LEN(seq); i++) { \
|
||||
TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \
|
||||
if (!symtable_visit_ ## TYPE((ST), elt)) \
|
||||
VISIT_QUIT((ST), 0); \
|
||||
return 0; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
@ -1661,10 +1661,25 @@ symtable_enter_type_param_block(struct symtable *st, identifier name,
|
||||
TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \
|
||||
if (!elt) continue; /* can be NULL */ \
|
||||
if (!symtable_visit_ ## TYPE((ST), elt)) \
|
||||
VISIT_QUIT((ST), 0); \
|
||||
return 0; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define ENTER_RECURSIVE(ST) \
|
||||
do { \
|
||||
if (++(ST)->recursion_depth > (ST)->recursion_limit) { \
|
||||
PyErr_SetString(PyExc_RecursionError, \
|
||||
"maximum recursion depth exceeded during compilation"); \
|
||||
return 0; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LEAVE_RECURSIVE(ST) \
|
||||
do { \
|
||||
--(ST)->recursion_depth; \
|
||||
} while(0)
|
||||
|
||||
|
||||
static int
|
||||
symtable_record_directive(struct symtable *st, identifier name, _Py_SourceLocation loc)
|
||||
{
|
||||
@ -1737,15 +1752,11 @@ maybe_set_ste_coroutine_for_module(struct symtable *st, stmt_ty s)
|
||||
static int
|
||||
symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
{
|
||||
if (++st->recursion_depth > st->recursion_limit) {
|
||||
PyErr_SetString(PyExc_RecursionError,
|
||||
"maximum recursion depth exceeded during compilation");
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
ENTER_RECURSIVE(st);
|
||||
switch (s->kind) {
|
||||
case FunctionDef_kind: {
|
||||
if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL, LOCATION(s)))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
if (s->v.FunctionDef.args->defaults)
|
||||
VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults);
|
||||
if (s->v.FunctionDef.args->kw_defaults)
|
||||
@ -1761,40 +1772,40 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
s->v.FunctionDef.args->kw_defaults),
|
||||
s->kind,
|
||||
LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
VISIT_SEQ(st, type_param, s->v.FunctionDef.type_params);
|
||||
}
|
||||
PySTEntryObject *new_ste = ste_new(st, s->v.FunctionDef.name, FunctionBlock, (void *)s,
|
||||
LOCATION(s));
|
||||
if (!new_ste) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!symtable_visit_annotations(st, s, s->v.FunctionDef.args,
|
||||
s->v.FunctionDef.returns, new_ste)) {
|
||||
Py_DECREF(new_ste);
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
if (!symtable_enter_existing_block(st, new_ste)) {
|
||||
Py_DECREF(new_ste);
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
Py_DECREF(new_ste);
|
||||
VISIT(st, arguments, s->v.FunctionDef.args);
|
||||
VISIT_SEQ(st, stmt, s->v.FunctionDef.body);
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
if (asdl_seq_LEN(s->v.FunctionDef.type_params) > 0) {
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ClassDef_kind: {
|
||||
PyObject *tmp;
|
||||
if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL, LOCATION(s)))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
if (s->v.ClassDef.decorator_list)
|
||||
VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list);
|
||||
tmp = st->st_private;
|
||||
@ -1803,42 +1814,42 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
(void *)s->v.ClassDef.type_params,
|
||||
false, false, s->kind,
|
||||
LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
st->st_private = s->v.ClassDef.name;
|
||||
st->st_cur->ste_mangled_names = PySet_New(NULL);
|
||||
if (!st->st_cur->ste_mangled_names) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
VISIT_SEQ(st, type_param, s->v.ClassDef.type_params);
|
||||
}
|
||||
VISIT_SEQ(st, expr, s->v.ClassDef.bases);
|
||||
if (!check_keywords(st, s->v.ClassDef.keywords)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
VISIT_SEQ(st, keyword, s->v.ClassDef.keywords);
|
||||
if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock,
|
||||
(void *)s, LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
st->st_private = s->v.ClassDef.name;
|
||||
if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) {
|
||||
if (!symtable_add_def(st, &_Py_ID(__type_params__),
|
||||
DEF_LOCAL, LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
_Py_DECLARE_STR(type_params, ".type_params");
|
||||
if (!symtable_add_def(st, &_Py_STR(type_params),
|
||||
USE, LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
VISIT_SEQ(st, stmt, s->v.ClassDef.body);
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) {
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
st->st_private = tmp;
|
||||
break;
|
||||
@ -1855,24 +1866,24 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
(void *)s->v.TypeAlias.type_params,
|
||||
false, false, s->kind,
|
||||
LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
VISIT_SEQ(st, type_param, s->v.TypeAlias.type_params);
|
||||
}
|
||||
if (!symtable_enter_block(st, name, TypeAliasBlock,
|
||||
(void *)s, LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
st->st_cur->ste_can_see_class_scope = is_in_class;
|
||||
if (is_in_class && !symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(s->v.TypeAlias.value))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
VISIT(st, expr, s->v.TypeAlias.value);
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
if (is_generic) {
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1895,7 +1906,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
expr_ty e_name = s->v.AnnAssign.target;
|
||||
long cur = symtable_lookup(st, e_name->v.Name.id);
|
||||
if (cur < 0) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
if ((cur & (DEF_GLOBAL | DEF_NONLOCAL))
|
||||
&& (st->st_cur->ste_symbols != st->st_global)
|
||||
@ -1904,17 +1915,17 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
cur & DEF_GLOBAL ? GLOBAL_ANNOT : NONLOCAL_ANNOT,
|
||||
e_name->v.Name.id);
|
||||
SET_ERROR_LOCATION(st->st_filename, LOCATION(s));
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
if (s->v.AnnAssign.simple &&
|
||||
!symtable_add_def(st, e_name->v.Name.id,
|
||||
DEF_ANNOT | DEF_LOCAL, LOCATION(e_name))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
if (s->v.AnnAssign.value
|
||||
&& !symtable_add_def(st, e_name->v.Name.id, DEF_LOCAL, LOCATION(e_name))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1923,7 +1934,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
}
|
||||
if (!symtable_visit_annotation(st, s->v.AnnAssign.annotation,
|
||||
(void *)((uintptr_t)st->st_cur->ste_id + 1))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->v.AnnAssign.value) {
|
||||
@ -1990,7 +2001,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
case ImportFrom_kind:
|
||||
VISIT_SEQ(st, alias, s->v.ImportFrom.names);
|
||||
if (!check_import_from(st, s)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case Global_kind: {
|
||||
@ -2000,7 +2011,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
identifier name = (identifier)asdl_seq_GET(seq, i);
|
||||
long cur = symtable_lookup(st, name);
|
||||
if (cur < 0)
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
if (cur & (DEF_PARAM | DEF_LOCAL | USE | DEF_ANNOT)) {
|
||||
const char* msg;
|
||||
if (cur & DEF_PARAM) {
|
||||
@ -2015,13 +2026,13 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
PyErr_Format(PyExc_SyntaxError,
|
||||
msg, name);
|
||||
SET_ERROR_LOCATION(st->st_filename, LOCATION(s));
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
if (!symtable_add_def(st, name, DEF_GLOBAL, LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
if (!symtable_record_directive(st, name, LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2033,7 +2044,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
identifier name = (identifier)asdl_seq_GET(seq, i);
|
||||
long cur = symtable_lookup(st, name);
|
||||
if (cur < 0)
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
if (cur & (DEF_PARAM | DEF_LOCAL | USE | DEF_ANNOT)) {
|
||||
const char* msg;
|
||||
if (cur & DEF_PARAM) {
|
||||
@ -2047,12 +2058,12 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
}
|
||||
PyErr_Format(PyExc_SyntaxError, msg, name);
|
||||
SET_ERROR_LOCATION(st->st_filename, LOCATION(s));
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
if (!symtable_add_def(st, name, DEF_NONLOCAL, LOCATION(s)))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
if (!symtable_record_directive(st, name, LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2071,7 +2082,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
break;
|
||||
case AsyncFunctionDef_kind: {
|
||||
if (!symtable_add_def(st, s->v.AsyncFunctionDef.name, DEF_LOCAL, LOCATION(s)))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
if (s->v.AsyncFunctionDef.args->defaults)
|
||||
VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.args->defaults);
|
||||
if (s->v.AsyncFunctionDef.args->kw_defaults)
|
||||
@ -2088,24 +2099,24 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
s->v.AsyncFunctionDef.args->kw_defaults),
|
||||
s->kind,
|
||||
LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
VISIT_SEQ(st, type_param, s->v.AsyncFunctionDef.type_params);
|
||||
}
|
||||
PySTEntryObject *new_ste = ste_new(st, s->v.FunctionDef.name, FunctionBlock, (void *)s,
|
||||
LOCATION(s));
|
||||
if (!new_ste) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!symtable_visit_annotations(st, s, s->v.AsyncFunctionDef.args,
|
||||
s->v.AsyncFunctionDef.returns, new_ste)) {
|
||||
Py_DECREF(new_ste);
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
if (!symtable_enter_existing_block(st, new_ste)) {
|
||||
Py_DECREF(new_ste);
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
Py_DECREF(new_ste);
|
||||
|
||||
@ -2113,17 +2124,17 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
VISIT(st, arguments, s->v.AsyncFunctionDef.args);
|
||||
VISIT_SEQ(st, stmt, s->v.AsyncFunctionDef.body);
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
if (asdl_seq_LEN(s->v.AsyncFunctionDef.type_params) > 0) {
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AsyncWith_kind:
|
||||
maybe_set_ste_coroutine_for_module(st, s);
|
||||
if (!symtable_raise_if_not_coroutine(st, ASYNC_WITH_OUTSIDE_ASYNC_FUNC, LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
VISIT_SEQ(st, withitem, s->v.AsyncWith.items);
|
||||
VISIT_SEQ(st, stmt, s->v.AsyncWith.body);
|
||||
@ -2131,7 +2142,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
case AsyncFor_kind:
|
||||
maybe_set_ste_coroutine_for_module(st, s);
|
||||
if (!symtable_raise_if_not_coroutine(st, ASYNC_FOR_OUTSIDE_ASYNC_FUNC, LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
VISIT(st, expr, s->v.AsyncFor.target);
|
||||
VISIT(st, expr, s->v.AsyncFor.iter);
|
||||
@ -2140,7 +2151,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
VISIT_SEQ(st, stmt, s->v.AsyncFor.orelse);
|
||||
break;
|
||||
}
|
||||
VISIT_QUIT(st, 1);
|
||||
LEAVE_RECURSIVE(st);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2168,7 +2180,7 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e)
|
||||
(target_in_scope & DEF_LOCAL)) {
|
||||
PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_CONFLICT, target_name);
|
||||
SET_ERROR_LOCATION(st->st_filename, LOCATION(e));
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -2178,14 +2190,14 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e)
|
||||
long target_in_scope = symtable_lookup_entry(st, ste, target_name);
|
||||
if (target_in_scope & DEF_GLOBAL) {
|
||||
if (!symtable_add_def(st, target_name, DEF_GLOBAL, LOCATION(e)))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
} else {
|
||||
if (!symtable_add_def(st, target_name, DEF_NONLOCAL, LOCATION(e))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!symtable_record_directive(st, target_name, LOCATION(e))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return symtable_add_def_helper(st, target_name, DEF_LOCAL, ste, LOCATION(e));
|
||||
@ -2193,10 +2205,10 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e)
|
||||
/* If we find a ModuleBlock entry, add as GLOBAL */
|
||||
if (ste->ste_type == ModuleBlock) {
|
||||
if (!symtable_add_def(st, target_name, DEF_GLOBAL, LOCATION(e))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
if (!symtable_record_directive(st, target_name, LOCATION(e))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return symtable_add_def_helper(st, target_name, DEF_GLOBAL, ste, LOCATION(e));
|
||||
@ -2223,7 +2235,7 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e)
|
||||
Py_UNREACHABLE();
|
||||
}
|
||||
SET_ERROR_LOCATION(st->st_filename, LOCATION(e));
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2256,18 +2268,14 @@ symtable_handle_namedexpr(struct symtable *st, expr_ty e)
|
||||
static int
|
||||
symtable_visit_expr(struct symtable *st, expr_ty e)
|
||||
{
|
||||
if (++st->recursion_depth > st->recursion_limit) {
|
||||
PyErr_SetString(PyExc_RecursionError,
|
||||
"maximum recursion depth exceeded during compilation");
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
ENTER_RECURSIVE(st);
|
||||
switch (e->kind) {
|
||||
case NamedExpr_kind:
|
||||
if (!symtable_raise_if_annotation_block(st, "named expression", e)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
if(!symtable_handle_namedexpr(st, e))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
break;
|
||||
case BoolOp_kind:
|
||||
VISIT_SEQ(st, expr, e->v.BoolOp.values);
|
||||
@ -2286,12 +2294,12 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
|
||||
VISIT_SEQ_WITH_NULL(st, expr, e->v.Lambda.args->kw_defaults);
|
||||
if (!symtable_enter_block(st, &_Py_ID(lambda),
|
||||
FunctionBlock, (void *)e, LOCATION(e))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
VISIT(st, arguments, e->v.Lambda.args);
|
||||
VISIT(st, expr, e->v.Lambda.body);
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
case IfExp_kind:
|
||||
@ -2308,23 +2316,23 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
|
||||
break;
|
||||
case GeneratorExp_kind:
|
||||
if (!symtable_visit_genexp(st, e))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
break;
|
||||
case ListComp_kind:
|
||||
if (!symtable_visit_listcomp(st, e))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
break;
|
||||
case SetComp_kind:
|
||||
if (!symtable_visit_setcomp(st, e))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
break;
|
||||
case DictComp_kind:
|
||||
if (!symtable_visit_dictcomp(st, e))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
break;
|
||||
case Yield_kind:
|
||||
if (!symtable_raise_if_annotation_block(st, "yield expression", e)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
if (e->v.Yield.value)
|
||||
VISIT(st, expr, e->v.Yield.value);
|
||||
@ -2335,7 +2343,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
|
||||
break;
|
||||
case YieldFrom_kind:
|
||||
if (!symtable_raise_if_annotation_block(st, "yield expression", e)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
VISIT(st, expr, e->v.YieldFrom.value);
|
||||
st->st_cur->ste_generator = 1;
|
||||
@ -2345,20 +2353,20 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
|
||||
break;
|
||||
case Await_kind:
|
||||
if (!symtable_raise_if_annotation_block(st, "await expression", e)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
if (!allows_top_level_await(st)) {
|
||||
if (!_PyST_IsFunctionLike(st->st_cur)) {
|
||||
PyErr_SetString(PyExc_SyntaxError,
|
||||
"'await' outside function");
|
||||
SET_ERROR_LOCATION(st->st_filename, LOCATION(e));
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
if (!IS_ASYNC_DEF(st) && st->st_cur->ste_comprehension == NoComprehension) {
|
||||
PyErr_SetString(PyExc_SyntaxError,
|
||||
"'await' outside async function");
|
||||
SET_ERROR_LOCATION(st->st_filename, LOCATION(e));
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
VISIT(st, expr, e->v.Await.value);
|
||||
@ -2372,7 +2380,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
|
||||
VISIT(st, expr, e->v.Call.func);
|
||||
VISIT_SEQ(st, expr, e->v.Call.args);
|
||||
if (!check_keywords(st, e->v.Call.keywords)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
VISIT_SEQ_WITH_NULL(st, keyword, e->v.Call.keywords);
|
||||
break;
|
||||
@ -2390,7 +2398,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
|
||||
/* The following exprs can be assignment targets. */
|
||||
case Attribute_kind:
|
||||
if (!check_name(st, e->v.Attribute.attr, LOCATION(e), e->v.Attribute.ctx)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
VISIT(st, expr, e->v.Attribute.value);
|
||||
break;
|
||||
@ -2413,14 +2421,14 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
|
||||
if (!symtable_add_def_ctx(st, e->v.Name.id,
|
||||
e->v.Name.ctx == Load ? USE : DEF_LOCAL,
|
||||
LOCATION(e), e->v.Name.ctx)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
/* Special-case super: it counts as a use of __class__ */
|
||||
if (e->v.Name.ctx == Load &&
|
||||
_PyST_IsFunctionLike(st->st_cur) &&
|
||||
_PyUnicode_EqualToASCIIString(e->v.Name.id, "super")) {
|
||||
if (!symtable_add_def(st, &_Py_ID(__class__), USE, LOCATION(e)))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
/* child nodes of List and Tuple will have expr_context set */
|
||||
@ -2431,7 +2439,8 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
|
||||
VISIT_SEQ(st, expr, e->v.Tuple.elts);
|
||||
break;
|
||||
}
|
||||
VISIT_QUIT(st, 1);
|
||||
LEAVE_RECURSIVE(st);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2447,7 +2456,7 @@ symtable_visit_type_param_bound_or_default(
|
||||
|
||||
st->st_cur->ste_can_see_class_scope = is_in_class;
|
||||
if (is_in_class && !symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(e))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(ste_scope_info != NULL);
|
||||
@ -2464,15 +2473,11 @@ symtable_visit_type_param_bound_or_default(
|
||||
static int
|
||||
symtable_visit_type_param(struct symtable *st, type_param_ty tp)
|
||||
{
|
||||
if (++st->recursion_depth > st->recursion_limit) {
|
||||
PyErr_SetString(PyExc_RecursionError,
|
||||
"maximum recursion depth exceeded during compilation");
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
ENTER_RECURSIVE(st);
|
||||
switch(tp->kind) {
|
||||
case TypeVar_kind:
|
||||
if (!symtable_add_def(st, tp->v.TypeVar.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp)))
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
|
||||
const char *ste_scope_info = NULL;
|
||||
const expr_ty bound = tp->v.TypeVar.bound;
|
||||
@ -2488,46 +2493,43 @@ symtable_visit_type_param(struct symtable *st, type_param_ty tp)
|
||||
// compile.c where the scope is retrieved.
|
||||
if (!symtable_visit_type_param_bound_or_default(st, tp->v.TypeVar.bound, tp->v.TypeVar.name,
|
||||
(void *)tp, ste_scope_info)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!symtable_visit_type_param_bound_or_default(st, tp->v.TypeVar.default_value, tp->v.TypeVar.name,
|
||||
(void *)((uintptr_t)tp + 1), "a TypeVar default")) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case TypeVarTuple_kind:
|
||||
if (!symtable_add_def(st, tp->v.TypeVarTuple.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!symtable_visit_type_param_bound_or_default(st, tp->v.TypeVarTuple.default_value, tp->v.TypeVarTuple.name,
|
||||
(void *)tp, "a TypeVarTuple default")) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ParamSpec_kind:
|
||||
if (!symtable_add_def(st, tp->v.ParamSpec.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!symtable_visit_type_param_bound_or_default(st, tp->v.ParamSpec.default_value, tp->v.ParamSpec.name,
|
||||
(void *)tp, "a ParamSpec default")) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
VISIT_QUIT(st, 1);
|
||||
LEAVE_RECURSIVE(st);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
symtable_visit_pattern(struct symtable *st, pattern_ty p)
|
||||
{
|
||||
if (++st->recursion_depth > st->recursion_limit) {
|
||||
PyErr_SetString(PyExc_RecursionError,
|
||||
"maximum recursion depth exceeded during compilation");
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
ENTER_RECURSIVE(st);
|
||||
switch (p->kind) {
|
||||
case MatchValue_kind:
|
||||
VISIT(st, expr, p->v.MatchValue.value);
|
||||
@ -2541,7 +2543,7 @@ symtable_visit_pattern(struct symtable *st, pattern_ty p)
|
||||
case MatchStar_kind:
|
||||
if (p->v.MatchStar.name) {
|
||||
if (!symtable_add_def(st, p->v.MatchStar.name, DEF_LOCAL, LOCATION(p))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2550,7 +2552,7 @@ symtable_visit_pattern(struct symtable *st, pattern_ty p)
|
||||
VISIT_SEQ(st, pattern, p->v.MatchMapping.patterns);
|
||||
if (p->v.MatchMapping.rest) {
|
||||
if (!symtable_add_def(st, p->v.MatchMapping.rest, DEF_LOCAL, LOCATION(p))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2558,7 +2560,7 @@ symtable_visit_pattern(struct symtable *st, pattern_ty p)
|
||||
VISIT(st, expr, p->v.MatchClass.cls);
|
||||
VISIT_SEQ(st, pattern, p->v.MatchClass.patterns);
|
||||
if (!check_kwd_patterns(st, p)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
VISIT_SEQ(st, pattern, p->v.MatchClass.kwd_patterns);
|
||||
break;
|
||||
@ -2568,7 +2570,7 @@ symtable_visit_pattern(struct symtable *st, pattern_ty p)
|
||||
}
|
||||
if (p->v.MatchAs.name) {
|
||||
if (!symtable_add_def(st, p->v.MatchAs.name, DEF_LOCAL, LOCATION(p))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2576,7 +2578,8 @@ symtable_visit_pattern(struct symtable *st, pattern_ty p)
|
||||
VISIT_SEQ(st, pattern, p->v.MatchOr.patterns);
|
||||
break;
|
||||
}
|
||||
VISIT_QUIT(st, 1);
|
||||
LEAVE_RECURSIVE(st);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2618,7 +2621,7 @@ symtable_visit_annotation(struct symtable *st, expr_ty annotation, void *key)
|
||||
_Py_block_ty current_type = parent_ste->ste_type;
|
||||
if (!symtable_enter_block(st, &_Py_ID(__annotate__), AnnotationBlock,
|
||||
key, LOCATION(annotation))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
parent_ste->ste_annotation_block =
|
||||
(struct _symtable_entry *)Py_NewRef(st->st_cur);
|
||||
@ -2632,12 +2635,12 @@ symtable_visit_annotation(struct symtable *st, expr_ty annotation, void *key)
|
||||
}
|
||||
else {
|
||||
if (!symtable_enter_existing_block(st, parent_ste->ste_annotation_block)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
VISIT(st, expr, annotation);
|
||||
if (!symtable_exit_block(st)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -2669,7 +2672,7 @@ symtable_visit_annotations(struct symtable *st, stmt_ty o, arguments_ty a, expr_
|
||||
_Py_block_ty current_type = st->st_cur->ste_type;
|
||||
if (!symtable_enter_block(st, &_Py_ID(__annotate__), AnnotationBlock,
|
||||
(void *)a, LOCATION(o))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
if (is_in_class || current_type == ClassBlock) {
|
||||
st->st_cur->ste_can_see_class_scope = 1;
|
||||
@ -2696,7 +2699,7 @@ symtable_visit_annotations(struct symtable *st, stmt_ty o, arguments_ty a, expr_
|
||||
VISIT(st, expr, returns);
|
||||
}
|
||||
if (!symtable_exit_block(st)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -2963,7 +2966,7 @@ symtable_raise_if_comprehension_block(struct symtable *st, expr_ty e) {
|
||||
(type == DictComprehension) ? "'yield' inside dict comprehension" :
|
||||
"'yield' inside generator expression");
|
||||
SET_ERROR_LOCATION(st->st_filename, LOCATION(e));
|
||||
VISIT_QUIT(st, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
Loading…
Reference in New Issue
Block a user