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:
Serhiy Storchaka 2024-08-03 12:45:45 +03:00 committed by GitHub
parent fe0a28d850
commit efcd65cd84
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 164 additions and 162 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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