Coverage Report

Created: 2026-08-13 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython3/Python/ast_preprocess.c
Line
Count
Source
1
/* AST pre-processing */
2
#include "Python.h"
3
#include "pycore_ast.h"           // _PyAST_GetDocString()
4
#include "pycore_c_array.h"       // _Py_CArray_EnsureCapacity()
5
#include "pycore_format.h"        // F_LJUST
6
#include "pycore_runtime.h"       // _Py_STR()
7
#include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString()
8
9
10
/* See PEP 765 */
11
typedef struct {
12
    bool in_finally;
13
    bool in_funcdef;
14
    bool in_loop;
15
} ControlFlowInFinallyContext;
16
17
typedef struct {
18
    PyObject *filename;
19
    PyObject *module;
20
    int optimize;
21
    int ff_features;
22
    int syntax_check_only;
23
    int enable_warnings;
24
25
    _Py_c_array_t cf_finally;       /* context for PEP 765 check */
26
    int cf_finally_used;
27
} _PyASTPreprocessState;
28
29
2.82M
#define ENTER_RECURSIVE() \
30
2.82M
if (Py_EnterRecursiveCall(" during compilation")) { \
31
0
    return 0; \
32
0
}
33
34
2.82M
#define LEAVE_RECURSIVE() Py_LeaveRecursiveCall();
35
36
static ControlFlowInFinallyContext*
37
get_cf_finally_top(_PyASTPreprocessState *state)
38
18.5k
{
39
18.5k
    int idx = state->cf_finally_used;
40
18.5k
    return ((ControlFlowInFinallyContext*)state->cf_finally.array) + idx;
41
18.5k
}
42
43
static int
44
push_cf_context(_PyASTPreprocessState *state, stmt_ty node, bool finally, bool funcdef, bool loop)
45
18.0k
{
46
18.0k
    if (_Py_CArray_EnsureCapacity(&state->cf_finally, state->cf_finally_used+1) < 0) {
47
0
        return 0;
48
0
    }
49
50
18.0k
    state->cf_finally_used++;
51
18.0k
    ControlFlowInFinallyContext *ctx = get_cf_finally_top(state);
52
53
18.0k
    ctx->in_finally = finally;
54
18.0k
    ctx->in_funcdef = funcdef;
55
18.0k
    ctx->in_loop = loop;
56
18.0k
    return 1;
57
18.0k
}
58
59
static void
60
pop_cf_context(_PyASTPreprocessState *state)
61
18.0k
{
62
18.0k
    assert(state->cf_finally_used > 0);
63
18.0k
    state->cf_finally_used--;
64
18.0k
}
65
66
static int
67
control_flow_in_finally_warning(const char *kw, stmt_ty n, _PyASTPreprocessState *state)
68
231
{
69
231
    PyObject *msg = PyUnicode_FromFormat("'%s' in a 'finally' block", kw);
70
231
    if (msg == NULL) {
71
0
        return 0;
72
0
    }
73
231
    int ret = _PyErr_EmitSyntaxWarning(msg, state->filename, n->lineno,
74
231
                                       n->col_offset + 1, n->end_lineno,
75
231
                                       n->end_col_offset + 1,
76
231
                                       state->module);
77
231
    Py_DECREF(msg);
78
231
    return ret < 0 ? 0 : 1;
79
231
}
80
81
static int
82
before_return(_PyASTPreprocessState *state, stmt_ty node_)
83
1.06k
{
84
1.06k
    if (state->enable_warnings && state->cf_finally_used > 0) {
85
246
        ControlFlowInFinallyContext *ctx = get_cf_finally_top(state);
86
246
        if (ctx->in_finally && ! ctx->in_funcdef) {
87
23
            if (!control_flow_in_finally_warning("return", node_, state)) {
88
0
                return 0;
89
0
            }
90
23
        }
91
246
    }
92
1.06k
    return 1;
93
1.06k
}
94
95
static int
96
before_loop_exit(_PyASTPreprocessState *state, stmt_ty node_, const char *kw)
97
1.09k
{
98
1.09k
    if (state->enable_warnings && state->cf_finally_used > 0) {
99
323
        ControlFlowInFinallyContext *ctx = get_cf_finally_top(state);
100
323
        if (ctx->in_finally && ! ctx->in_loop) {
101
208
            if (!control_flow_in_finally_warning(kw, node_, state)) {
102
0
                return 0;
103
0
            }
104
208
        }
105
323
    }
106
1.09k
    return 1;
107
1.09k
}
108
109
#define PUSH_CONTEXT(S, N, FINALLY, FUNCDEF, LOOP) \
110
18.0k
    if (!push_cf_context((S), (N), (FINALLY), (FUNCDEF), (LOOP))) { \
111
0
        return 0; \
112
0
    }
113
114
18.0k
#define POP_CONTEXT(S) pop_cf_context(S)
115
116
4.84k
#define BEFORE_FINALLY(S, N)    PUSH_CONTEXT((S), (N), true, false, false)
117
4.84k
#define AFTER_FINALLY(S)        POP_CONTEXT(S)
118
9.63k
#define BEFORE_FUNC_BODY(S, N)  PUSH_CONTEXT((S), (N), false, true, false)
119
9.63k
#define AFTER_FUNC_BODY(S)      POP_CONTEXT(S)
120
3.54k
#define BEFORE_LOOP_BODY(S, N)  PUSH_CONTEXT((S), (N), false, false, true)
121
3.54k
#define AFTER_LOOP_BODY(S)      POP_CONTEXT(S)
122
123
#define BEFORE_RETURN(S, N) \
124
1.06k
    if (!before_return((S), (N))) { \
125
0
        return 0; \
126
0
    }
127
128
#define BEFORE_LOOP_EXIT(S, N, KW) \
129
1.09k
    if (!before_loop_exit((S), (N), (KW))) { \
130
0
        return 0; \
131
0
    }
132
133
static int
134
make_const(expr_ty node, PyObject *val, PyArena *arena)
135
294
{
136
    // Even if no new value was calculated, make_const may still
137
    // need to clear an error (e.g. for division by zero)
138
294
    if (val == NULL) {
139
0
        if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
140
0
            return 0;
141
0
        }
142
0
        PyErr_Clear();
143
0
        return 1;
144
0
    }
145
294
    if (_PyArena_AddPyObject(arena, val) < 0) {
146
0
        Py_DECREF(val);
147
0
        return 0;
148
0
    }
149
294
    node->kind = Constant_kind;
150
294
    node->v.Constant.kind = NULL;
151
294
    node->v.Constant.value = val;
152
294
    return 1;
153
294
}
154
155
806
#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
156
157
static int
158
has_starred(asdl_expr_seq *elts)
159
6.86k
{
160
6.86k
    Py_ssize_t n = asdl_seq_LEN(elts);
161
14.0k
    for (Py_ssize_t i = 0; i < n; i++) {
162
7.23k
        expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
163
7.23k
        if (e->kind == Starred_kind) {
164
3
            return 1;
165
3
        }
166
7.23k
    }
167
6.85k
    return 0;
168
6.86k
}
169
170
static expr_ty
171
parse_literal(PyObject *fmt, Py_ssize_t *ppos, PyArena *arena)
172
7.95k
{
173
7.95k
    const void *data = PyUnicode_DATA(fmt);
174
7.95k
    int kind = PyUnicode_KIND(fmt);
175
7.95k
    Py_ssize_t size = PyUnicode_GET_LENGTH(fmt);
176
7.95k
    Py_ssize_t start, pos;
177
7.95k
    int has_percents = 0;
178
7.95k
    start = pos = *ppos;
179
390k
    while (pos < size) {
180
388k
        if (PyUnicode_READ(kind, data, pos) != '%') {
181
345k
            pos++;
182
345k
        }
183
43.3k
        else if (pos+1 < size && PyUnicode_READ(kind, data, pos+1) == '%') {
184
37.8k
            has_percents = 1;
185
37.8k
            pos += 2;
186
37.8k
        }
187
5.54k
        else {
188
5.54k
            break;
189
5.54k
        }
190
388k
    }
191
7.95k
    *ppos = pos;
192
7.95k
    if (pos == start) {
193
213
        return NULL;
194
213
    }
195
7.74k
    PyObject *str = PyUnicode_Substring(fmt, start, pos);
196
    /* str = str.replace('%%', '%') */
197
7.74k
    if (str && has_percents) {
198
3.82k
        _Py_DECLARE_STR(dbl_percent, "%%");
199
3.82k
        Py_SETREF(str, PyUnicode_Replace(str, &_Py_STR(dbl_percent),
200
3.82k
                                         _Py_LATIN1_CHR('%'), -1));
201
3.82k
    }
202
7.74k
    if (!str) {
203
0
        return NULL;
204
0
    }
205
206
7.74k
    if (_PyArena_AddPyObject(arena, str) < 0) {
207
0
        Py_DECREF(str);
208
0
        return NULL;
209
0
    }
210
7.74k
    return _PyAST_Constant(str, NULL, -1, -1, -1, -1, arena);
211
7.74k
}
212
213
3.33k
#define MAXDIGITS 3
214
215
static int
216
simple_format_arg_parse(PyObject *fmt, Py_ssize_t *ppos,
217
                        int *spec, int *flags, int *width, int *prec)
218
5.13k
{
219
5.13k
    Py_ssize_t pos = *ppos, len = PyUnicode_GET_LENGTH(fmt);
220
5.13k
    Py_UCS4 ch;
221
222
15.6k
#define NEXTC do {                      \
223
15.6k
    if (pos >= len) {                   \
224
1.24k
        return 0;                       \
225
1.24k
    }                                   \
226
15.6k
    ch = PyUnicode_READ_CHAR(fmt, pos); \
227
14.4k
    pos++;                              \
228
14.4k
} while (0)
229
230
5.13k
    *flags = 0;
231
11.2k
    while (1) {
232
11.2k
        NEXTC;
233
10.5k
        switch (ch) {
234
960
            case '-': *flags |= F_LJUST; continue;
235
267
            case '+': *flags |= F_SIGN; continue;
236
730
            case ' ': *flags |= F_BLANK; continue;
237
292
            case '#': *flags |= F_ALT; continue;
238
3.84k
            case '0': *flags |= F_ZERO; continue;
239
10.5k
        }
240
4.50k
        break;
241
10.5k
    }
242
4.50k
    if ('0' <= ch && ch <= '9') {
243
1.57k
        *width = 0;
244
1.57k
        int digits = 0;
245
3.04k
        while ('0' <= ch && ch <= '9') {
246
2.44k
            *width = *width * 10 + (ch - '0');
247
2.44k
            NEXTC;
248
1.83k
            if (++digits >= MAXDIGITS) {
249
372
                return 0;
250
372
            }
251
1.83k
        }
252
1.57k
    }
253
254
3.52k
    if (ch == '.') {
255
1.00k
        NEXTC;
256
1.00k
        *prec = 0;
257
1.00k
        if ('0' <= ch && ch <= '9') {
258
441
            int digits = 0;
259
1.22k
            while ('0' <= ch && ch <= '9') {
260
1.01k
                *prec = *prec * 10 + (ch - '0');
261
1.01k
                NEXTC;
262
1.01k
                if (++digits >= MAXDIGITS) {
263
234
                    return 0;
264
234
                }
265
1.01k
            }
266
441
        }
267
1.00k
    }
268
3.28k
    *spec = ch;
269
3.28k
    *ppos = pos;
270
3.28k
    return 1;
271
272
3.52k
#undef NEXTC
273
3.52k
}
274
275
static expr_ty
276
parse_format(PyObject *fmt, Py_ssize_t *ppos, expr_ty arg, PyArena *arena)
277
5.13k
{
278
5.13k
    int spec, flags, width = -1, prec = -1;
279
5.13k
    if (!simple_format_arg_parse(fmt, ppos, &spec, &flags, &width, &prec)) {
280
        // Unsupported format.
281
1.85k
        return NULL;
282
1.85k
    }
283
3.28k
    if (spec == 's' || spec == 'r' || spec == 'a') {
284
1.09k
        char buf[1 + MAXDIGITS + 1 + MAXDIGITS + 1], *p = buf;
285
1.09k
        if (!(flags & F_LJUST) && width > 0) {
286
433
            *p++ = '>';
287
433
        }
288
1.09k
        if (width >= 0) {
289
434
            p += snprintf(p, MAXDIGITS + 1, "%d", width);
290
434
        }
291
1.09k
        if (prec >= 0) {
292
50
            p += snprintf(p, MAXDIGITS + 2, ".%d", prec);
293
50
        }
294
1.09k
        expr_ty format_spec = NULL;
295
1.09k
        if (p != buf) {
296
483
            PyObject *str = PyUnicode_FromString(buf);
297
483
            if (str == NULL) {
298
0
                return NULL;
299
0
            }
300
483
            if (_PyArena_AddPyObject(arena, str) < 0) {
301
0
                Py_DECREF(str);
302
0
                return NULL;
303
0
            }
304
483
            format_spec = _PyAST_Constant(str, NULL, -1, -1, -1, -1, arena);
305
483
            if (format_spec == NULL) {
306
0
                return NULL;
307
0
            }
308
483
        }
309
1.09k
        return _PyAST_FormattedValue(arg, spec, format_spec,
310
1.09k
                                     arg->lineno, arg->col_offset,
311
1.09k
                                     arg->end_lineno, arg->end_col_offset,
312
1.09k
                                     arena);
313
1.09k
    }
314
    // Unsupported format.
315
2.18k
    return NULL;
316
3.28k
}
317
318
static int
319
optimize_format(expr_ty node, PyObject *fmt, asdl_expr_seq *elts, PyArena *arena)
320
6.85k
{
321
6.85k
    Py_ssize_t pos = 0;
322
6.85k
    Py_ssize_t cnt = 0;
323
6.85k
    asdl_expr_seq *seq = _Py_asdl_expr_seq_new(asdl_seq_LEN(elts) * 2 + 1, arena);
324
6.85k
    if (!seq) {
325
0
        return 0;
326
0
    }
327
6.85k
    seq->size = 0;
328
329
7.95k
    while (1) {
330
7.95k
        expr_ty lit = parse_literal(fmt, &pos, arena);
331
7.95k
        if (lit) {
332
7.74k
            asdl_seq_SET(seq, seq->size++, lit);
333
7.74k
        }
334
213
        else if (PyErr_Occurred()) {
335
0
            return 0;
336
0
        }
337
338
7.95k
        if (pos >= PyUnicode_GET_LENGTH(fmt)) {
339
2.41k
            break;
340
2.41k
        }
341
5.54k
        if (cnt >= asdl_seq_LEN(elts)) {
342
            // More format units than items.
343
402
            return 1;
344
402
        }
345
5.54k
        assert(PyUnicode_READ_CHAR(fmt, pos) == '%');
346
5.13k
        pos++;
347
5.13k
        expr_ty expr = parse_format(fmt, &pos, asdl_seq_GET(elts, cnt), arena);
348
5.13k
        cnt++;
349
5.13k
        if (!expr) {
350
4.04k
            return !PyErr_Occurred();
351
4.04k
        }
352
1.09k
        asdl_seq_SET(seq, seq->size++, expr);
353
1.09k
    }
354
2.41k
    if (cnt < asdl_seq_LEN(elts)) {
355
        // More items than format units.
356
1.60k
        return 1;
357
1.60k
    }
358
806
    expr_ty res = _PyAST_JoinedStr(seq,
359
806
                                   node->lineno, node->col_offset,
360
806
                                   node->end_lineno, node->end_col_offset,
361
806
                                   arena);
362
806
    if (!res) {
363
0
        return 0;
364
0
    }
365
806
    COPY_NODE(node, res);
366
//     PySys_FormatStderr("format = %R\n", fmt);
367
806
    return 1;
368
806
}
369
370
static int
371
fold_binop(expr_ty node, PyArena *arena, _PyASTPreprocessState *state)
372
742k
{
373
742k
    if (state->syntax_check_only) {
374
9.67k
        return 1;
375
9.67k
    }
376
732k
    expr_ty lhs, rhs;
377
732k
    lhs = node->v.BinOp.left;
378
732k
    rhs = node->v.BinOp.right;
379
732k
    if (lhs->kind != Constant_kind) {
380
501k
        return 1;
381
501k
    }
382
231k
    PyObject *lv = lhs->v.Constant.value;
383
384
231k
    if (node->v.BinOp.op == Mod &&
385
22.3k
        rhs->kind == Tuple_kind &&
386
231k
        PyUnicode_Check(lv) &&
387
6.86k
        !has_starred(rhs->v.Tuple.elts))
388
6.85k
    {
389
6.85k
        return optimize_format(node, lv, rhs->v.Tuple.elts, arena);
390
6.85k
    }
391
392
224k
    return 1;
393
231k
}
394
395
static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTPreprocessState *state);
396
static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTPreprocessState *state);
397
static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTPreprocessState *state);
398
static int astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTPreprocessState *state);
399
static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTPreprocessState *state);
400
static int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTPreprocessState *state);
401
static int astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTPreprocessState *state);
402
static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTPreprocessState *state);
403
static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTPreprocessState *state);
404
static int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTPreprocessState *state);
405
static int astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTPreprocessState *state);
406
static int astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTPreprocessState *state);
407
408
#define CALL(FUNC, TYPE, ARG) \
409
2.86M
    if (!FUNC((ARG), ctx_, state)) \
410
2.86M
        return 0;
411
412
#define CALL_OPT(FUNC, TYPE, ARG) \
413
176k
    if ((ARG) != NULL && !FUNC((ARG), ctx_, state)) \
414
176k
        return 0;
415
416
399k
#define CALL_SEQ(FUNC, TYPE, ARG) { \
417
399k
    Py_ssize_t i; \
418
399k
    asdl_ ## TYPE ## _seq *seq = (ARG); /* avoid variable capture */ \
419
1.16M
    for (i = 0; i < asdl_seq_LEN(seq); i++) { \
420
763k
        TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \
421
763k
        if (elt != NULL && !FUNC(elt, ctx_, state)) \
422
763k
            return 0; \
423
763k
    } \
424
399k
}
425
426
427
static int
428
stmt_seq_remove_item(asdl_stmt_seq *stmts, Py_ssize_t idx)
429
28
{
430
28
    if (idx >= asdl_seq_LEN(stmts)) {
431
0
        return 0;
432
0
    }
433
116
    for (Py_ssize_t i = idx; i < asdl_seq_LEN(stmts) - 1; i++) {
434
88
        stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, i+1);
435
88
        asdl_seq_SET(stmts, i, st);
436
88
    }
437
28
    stmts->size--;
438
28
    return 1;
439
28
}
440
441
static int
442
remove_docstring(asdl_stmt_seq *stmts, Py_ssize_t idx, PyArena *ctx_)
443
306
{
444
306
    assert(_PyAST_GetDocString(stmts) != NULL);
445
    // In case there's just the docstring in the body, replace it with `pass`
446
    // keyword, so body won't be empty.
447
306
    if (asdl_seq_LEN(stmts) == 1) {
448
278
        stmt_ty docstring = (stmt_ty)asdl_seq_GET(stmts, 0);
449
278
        stmt_ty pass = _PyAST_Pass(
450
278
            docstring->lineno, docstring->col_offset,
451
            // we know that `pass` always takes 4 chars and a single line,
452
            // while docstring can span on multiple lines
453
278
            docstring->lineno, docstring->col_offset + 4,
454
278
            ctx_
455
278
        );
456
278
        if (pass == NULL) {
457
0
            return 0;
458
0
        }
459
278
        asdl_seq_SET(stmts, 0, pass);
460
278
        return 1;
461
278
    }
462
    // In case there are more than 1 body items, just remove the docstring.
463
28
    return stmt_seq_remove_item(stmts, idx);
464
306
}
465
466
static int
467
astfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTPreprocessState *state)
468
31.4k
{
469
31.4k
    int docstring = _PyAST_GetDocString(stmts) != NULL;
470
31.4k
    if (docstring && (state->optimize >= 2)) {
471
        /* remove the docstring */
472
306
        if (!remove_docstring(stmts, 0, ctx_)) {
473
0
            return 0;
474
0
        }
475
306
        docstring = 0;
476
306
    }
477
31.4k
    CALL_SEQ(astfold_stmt, stmt, stmts);
478
31.4k
    if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
479
24
        stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
480
24
        asdl_expr_seq *values = _Py_asdl_expr_seq_new(1, ctx_);
481
24
        if (!values) {
482
0
            return 0;
483
0
        }
484
24
        asdl_seq_SET(values, 0, st->v.Expr.value);
485
24
        expr_ty expr = _PyAST_JoinedStr(values, st->lineno, st->col_offset,
486
24
                                        st->end_lineno, st->end_col_offset,
487
24
                                        ctx_);
488
24
        if (!expr) {
489
0
            return 0;
490
0
        }
491
24
        st->v.Expr.value = expr;
492
24
    }
493
31.4k
    return 1;
494
31.4k
}
495
496
static int
497
astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTPreprocessState *state)
498
12.7k
{
499
12.7k
    switch (node_->kind) {
500
8.73k
    case Module_kind:
501
8.73k
        CALL(astfold_body, asdl_seq, node_->v.Module.body);
502
8.73k
        break;
503
2.23k
    case Interactive_kind:
504
2.23k
        CALL_SEQ(astfold_stmt, stmt, node_->v.Interactive.body);
505
2.23k
        break;
506
1.74k
    case Expression_kind:
507
1.74k
        CALL(astfold_expr, expr_ty, node_->v.Expression.body);
508
1.74k
        break;
509
    // The following top level nodes don't participate in constant folding
510
0
    case FunctionType_kind:
511
0
        break;
512
    // No default case, so the compiler will emit a warning if new top level
513
    // compilation nodes are added without being handled here
514
12.7k
    }
515
12.7k
    return 1;
516
12.7k
}
517
518
static int
519
astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTPreprocessState *state)
520
2.58M
{
521
2.58M
    ENTER_RECURSIVE();
522
2.58M
    switch (node_->kind) {
523
3.64k
    case BoolOp_kind:
524
3.64k
        CALL_SEQ(astfold_expr, expr, node_->v.BoolOp.values);
525
3.64k
        break;
526
742k
    case BinOp_kind:
527
742k
        CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
528
742k
        CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
529
742k
        CALL(fold_binop, expr_ty, node_);
530
742k
        break;
531
235k
    case UnaryOp_kind:
532
235k
        CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
533
235k
        break;
534
4.79k
    case Lambda_kind:
535
4.79k
        CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
536
4.79k
        CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
537
4.79k
        break;
538
1.54k
    case IfExp_kind:
539
1.54k
        CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
540
1.54k
        CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
541
1.54k
        CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
542
1.54k
        break;
543
614
    case Dict_kind:
544
614
        CALL_SEQ(astfold_expr, expr, node_->v.Dict.keys);
545
614
        CALL_SEQ(astfold_expr, expr, node_->v.Dict.values);
546
614
        break;
547
7.12k
    case Set_kind:
548
7.12k
        CALL_SEQ(astfold_expr, expr, node_->v.Set.elts);
549
7.12k
        break;
550
1.51k
    case ListComp_kind:
551
1.51k
        CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
552
1.51k
        CALL_SEQ(astfold_comprehension, comprehension, node_->v.ListComp.generators);
553
1.51k
        break;
554
2.87k
    case SetComp_kind:
555
2.87k
        CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
556
2.87k
        CALL_SEQ(astfold_comprehension, comprehension, node_->v.SetComp.generators);
557
2.87k
        break;
558
904
    case DictComp_kind:
559
904
        CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
560
904
        if (node_->v.DictComp.value != NULL){
561
490
            CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
562
490
        }
563
904
        CALL_SEQ(astfold_comprehension, comprehension, node_->v.DictComp.generators);
564
904
        break;
565
605
    case GeneratorExp_kind:
566
605
        CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
567
605
        CALL_SEQ(astfold_comprehension, comprehension, node_->v.GeneratorExp.generators);
568
605
        break;
569
1.17k
    case Await_kind:
570
1.17k
        CALL(astfold_expr, expr_ty, node_->v.Await.value);
571
1.17k
        break;
572
1.50k
    case Yield_kind:
573
1.50k
        CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
574
1.50k
        break;
575
226
    case YieldFrom_kind:
576
226
        CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
577
226
        break;
578
20.4k
    case Compare_kind:
579
20.4k
        CALL(astfold_expr, expr_ty, node_->v.Compare.left);
580
20.4k
        CALL_SEQ(astfold_expr, expr, node_->v.Compare.comparators);
581
20.4k
        break;
582
13.6k
    case Call_kind:
583
13.6k
        CALL(astfold_expr, expr_ty, node_->v.Call.func);
584
13.6k
        CALL_SEQ(astfold_expr, expr, node_->v.Call.args);
585
13.6k
        CALL_SEQ(astfold_keyword, keyword, node_->v.Call.keywords);
586
13.6k
        break;
587
4.71k
    case FormattedValue_kind:
588
4.71k
        CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
589
4.71k
        CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
590
4.71k
        break;
591
1.93k
    case Interpolation_kind:
592
1.93k
        CALL(astfold_expr, expr_ty, node_->v.Interpolation.value);
593
1.93k
        CALL_OPT(astfold_expr, expr_ty, node_->v.Interpolation.format_spec);
594
1.93k
        break;
595
4.07k
    case JoinedStr_kind:
596
4.07k
        CALL_SEQ(astfold_expr, expr, node_->v.JoinedStr.values);
597
4.07k
        break;
598
1.19k
    case TemplateStr_kind:
599
1.19k
        CALL_SEQ(astfold_expr, expr, node_->v.TemplateStr.values);
600
1.19k
        break;
601
21.1k
    case Attribute_kind:
602
21.1k
        CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
603
21.1k
        break;
604
11.6k
    case Subscript_kind:
605
11.6k
        CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
606
11.6k
        CALL(astfold_expr, expr_ty, node_->v.Subscript.slice);
607
11.6k
        break;
608
10.8k
    case Starred_kind:
609
10.8k
        CALL(astfold_expr, expr_ty, node_->v.Starred.value);
610
10.8k
        break;
611
14.6k
    case Slice_kind:
612
14.6k
        CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
613
14.6k
        CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
614
14.6k
        CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
615
14.6k
        break;
616
3.10k
    case List_kind:
617
3.10k
        CALL_SEQ(astfold_expr, expr, node_->v.List.elts);
618
3.10k
        break;
619
84.4k
    case Tuple_kind:
620
84.4k
        CALL_SEQ(astfold_expr, expr, node_->v.Tuple.elts);
621
84.4k
        break;
622
488k
    case Name_kind:
623
488k
        if (state->syntax_check_only) {
624
46.5k
            break;
625
46.5k
        }
626
442k
        if (node_->v.Name.ctx == Load &&
627
294k
                _PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
628
254
            LEAVE_RECURSIVE();
629
254
            return make_const(node_, PyBool_FromLong(!state->optimize), ctx_);
630
254
        }
631
442k
        break;
632
442k
    case NamedExpr_kind:
633
2.11k
        CALL(astfold_expr, expr_ty, node_->v.NamedExpr.value);
634
2.11k
        break;
635
893k
    case Constant_kind:
636
        // Already a constant, nothing further to do
637
893k
        break;
638
    // No default case, so the compiler will emit a warning if new expression
639
    // kinds are added without being handled here
640
2.58M
    }
641
2.58M
    LEAVE_RECURSIVE();
642
2.58M
    return 1;
643
2.58M
}
644
645
static int
646
astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTPreprocessState *state)
647
2.61k
{
648
2.61k
    CALL(astfold_expr, expr_ty, node_->value);
649
2.61k
    return 1;
650
2.61k
}
651
652
static int
653
astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTPreprocessState *state)
654
6.59k
{
655
6.59k
    CALL(astfold_expr, expr_ty, node_->target);
656
6.59k
    CALL(astfold_expr, expr_ty, node_->iter);
657
6.59k
    CALL_SEQ(astfold_expr, expr, node_->ifs);
658
6.59k
    return 1;
659
6.59k
}
660
661
static int
662
astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTPreprocessState *state)
663
14.4k
{
664
14.4k
    CALL_SEQ(astfold_arg, arg, node_->posonlyargs);
665
14.4k
    CALL_SEQ(astfold_arg, arg, node_->args);
666
14.4k
    CALL_OPT(astfold_arg, arg_ty, node_->vararg);
667
14.4k
    CALL_SEQ(astfold_arg, arg, node_->kwonlyargs);
668
14.4k
    CALL_SEQ(astfold_expr, expr, node_->kw_defaults);
669
14.4k
    CALL_OPT(astfold_arg, arg_ty, node_->kwarg);
670
14.4k
    CALL_SEQ(astfold_expr, expr, node_->defaults);
671
14.4k
    return 1;
672
14.4k
}
673
674
static int
675
astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTPreprocessState *state)
676
13.1k
{
677
13.1k
    if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
678
11.8k
        CALL_OPT(astfold_expr, expr_ty, node_->annotation);
679
11.8k
    }
680
13.1k
    return 1;
681
13.1k
}
682
683
static int
684
astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTPreprocessState *state)
685
224k
{
686
224k
    ENTER_RECURSIVE();
687
224k
    switch (node_->kind) {
688
6.38k
    case FunctionDef_kind: {
689
6.38k
        CALL_SEQ(astfold_type_param, type_param, node_->v.FunctionDef.type_params);
690
6.38k
        CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
691
6.38k
        BEFORE_FUNC_BODY(state, node_);
692
6.38k
        CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
693
6.38k
        AFTER_FUNC_BODY(state);
694
6.38k
        CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list);
695
6.38k
        if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
696
3.57k
            CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
697
3.57k
        }
698
6.38k
        break;
699
6.38k
    }
700
6.38k
    case AsyncFunctionDef_kind: {
701
3.25k
        CALL_SEQ(astfold_type_param, type_param, node_->v.AsyncFunctionDef.type_params);
702
3.25k
        CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
703
3.25k
        BEFORE_FUNC_BODY(state, node_);
704
3.25k
        CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
705
3.25k
        AFTER_FUNC_BODY(state);
706
3.25k
        CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list);
707
3.25k
        if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
708
2.45k
            CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
709
2.45k
        }
710
3.25k
        break;
711
3.25k
    }
712
13.0k
    case ClassDef_kind:
713
13.0k
        CALL_SEQ(astfold_type_param, type_param, node_->v.ClassDef.type_params);
714
13.0k
        CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.bases);
715
13.0k
        CALL_SEQ(astfold_keyword, keyword, node_->v.ClassDef.keywords);
716
13.0k
        CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
717
13.0k
        CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.decorator_list);
718
13.0k
        break;
719
1.06k
    case Return_kind:
720
1.06k
        BEFORE_RETURN(state, node_);
721
1.06k
        CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
722
1.06k
        break;
723
1.39k
    case Delete_kind:
724
1.39k
        CALL_SEQ(astfold_expr, expr, node_->v.Delete.targets);
725
1.39k
        break;
726
9.70k
    case Assign_kind:
727
9.70k
        CALL_SEQ(astfold_expr, expr, node_->v.Assign.targets);
728
9.70k
        CALL(astfold_expr, expr_ty, node_->v.Assign.value);
729
9.70k
        break;
730
7.60k
    case AugAssign_kind:
731
7.60k
        CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
732
7.60k
        CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
733
7.60k
        break;
734
25.7k
    case AnnAssign_kind:
735
25.7k
        CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
736
25.7k
        if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
737
19.1k
            CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation);
738
19.1k
        }
739
25.7k
        CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
740
25.7k
        break;
741
629
    case TypeAlias_kind:
742
629
        CALL(astfold_expr, expr_ty, node_->v.TypeAlias.name);
743
629
        CALL_SEQ(astfold_type_param, type_param, node_->v.TypeAlias.type_params);
744
629
        CALL(astfold_expr, expr_ty, node_->v.TypeAlias.value);
745
629
        break;
746
1.06k
    case For_kind: {
747
1.06k
        CALL(astfold_expr, expr_ty, node_->v.For.target);
748
1.06k
        CALL(astfold_expr, expr_ty, node_->v.For.iter);
749
1.06k
        BEFORE_LOOP_BODY(state, node_);
750
1.06k
        CALL_SEQ(astfold_stmt, stmt, node_->v.For.body);
751
1.06k
        AFTER_LOOP_BODY(state);
752
1.06k
        CALL_SEQ(astfold_stmt, stmt, node_->v.For.orelse);
753
1.06k
        break;
754
1.06k
    }
755
228
    case AsyncFor_kind: {
756
228
        CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
757
228
        CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
758
228
        BEFORE_LOOP_BODY(state, node_);
759
228
        CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.body);
760
228
        AFTER_LOOP_BODY(state);
761
228
        CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.orelse);
762
228
        break;
763
228
    }
764
2.25k
    case While_kind: {
765
2.25k
        CALL(astfold_expr, expr_ty, node_->v.While.test);
766
2.25k
        BEFORE_LOOP_BODY(state, node_);
767
2.25k
        CALL_SEQ(astfold_stmt, stmt, node_->v.While.body);
768
2.25k
        AFTER_LOOP_BODY(state);
769
2.25k
        CALL_SEQ(astfold_stmt, stmt, node_->v.While.orelse);
770
2.25k
        break;
771
2.25k
    }
772
1.66k
    case If_kind:
773
1.66k
        CALL(astfold_expr, expr_ty, node_->v.If.test);
774
1.66k
        CALL_SEQ(astfold_stmt, stmt, node_->v.If.body);
775
1.66k
        CALL_SEQ(astfold_stmt, stmt, node_->v.If.orelse);
776
1.66k
        break;
777
712
    case With_kind:
778
712
        CALL_SEQ(astfold_withitem, withitem, node_->v.With.items);
779
712
        CALL_SEQ(astfold_stmt, stmt, node_->v.With.body);
780
712
        break;
781
2.43k
    case AsyncWith_kind:
782
2.43k
        CALL_SEQ(astfold_withitem, withitem, node_->v.AsyncWith.items);
783
2.43k
        CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncWith.body);
784
2.43k
        break;
785
1.02k
    case Raise_kind:
786
1.02k
        CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
787
1.02k
        CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
788
1.02k
        break;
789
3.22k
    case Try_kind: {
790
3.22k
        CALL_SEQ(astfold_stmt, stmt, node_->v.Try.body);
791
3.22k
        CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.Try.handlers);
792
3.22k
        CALL_SEQ(astfold_stmt, stmt, node_->v.Try.orelse);
793
3.22k
        BEFORE_FINALLY(state, node_);
794
3.22k
        CALL_SEQ(astfold_stmt, stmt, node_->v.Try.finalbody);
795
3.22k
        AFTER_FINALLY(state);
796
3.22k
        break;
797
3.22k
    }
798
1.62k
    case TryStar_kind: {
799
1.62k
        CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.body);
800
1.62k
        CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.TryStar.handlers);
801
1.62k
        CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.orelse);
802
1.62k
        BEFORE_FINALLY(state, node_);
803
1.62k
        CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.finalbody);
804
1.62k
        AFTER_FINALLY(state);
805
1.62k
        break;
806
1.62k
    }
807
2.75k
    case Assert_kind:
808
2.75k
        CALL(astfold_expr, expr_ty, node_->v.Assert.test);
809
2.75k
        CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
810
2.75k
        break;
811
129k
    case Expr_kind:
812
129k
        CALL(astfold_expr, expr_ty, node_->v.Expr.value);
813
129k
        break;
814
267
    case Match_kind:
815
267
        CALL(astfold_expr, expr_ty, node_->v.Match.subject);
816
267
        CALL_SEQ(astfold_match_case, match_case, node_->v.Match.cases);
817
267
        break;
818
396
    case Break_kind:
819
396
        BEFORE_LOOP_EXIT(state, node_, "break");
820
396
        break;
821
700
    case Continue_kind:
822
700
        BEFORE_LOOP_EXIT(state, node_, "continue");
823
700
        break;
824
    // The following statements don't contain any subexpressions to be folded
825
2.86k
    case Import_kind:
826
5.43k
    case ImportFrom_kind:
827
6.33k
    case Global_kind:
828
6.53k
    case Nonlocal_kind:
829
8.39k
    case Pass_kind:
830
8.39k
        break;
831
    // No default case, so the compiler will emit a warning if new statement
832
    // kinds are added without being handled here
833
224k
    }
834
224k
    LEAVE_RECURSIVE();
835
224k
    return 1;
836
224k
}
837
838
static int
839
astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTPreprocessState *state)
840
4.43k
{
841
4.43k
    switch (node_->kind) {
842
4.43k
    case ExceptHandler_kind:
843
4.43k
        CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
844
4.43k
        CALL_SEQ(astfold_stmt, stmt, node_->v.ExceptHandler.body);
845
4.43k
        break;
846
    // No default case, so the compiler will emit a warning if new handler
847
    // kinds are added without being handled here
848
4.43k
    }
849
4.43k
    return 1;
850
4.43k
}
851
852
static int
853
astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTPreprocessState *state)
854
13.7k
{
855
13.7k
    CALL(astfold_expr, expr_ty, node_->context_expr);
856
13.7k
    CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
857
13.7k
    return 1;
858
13.7k
}
859
860
static int
861
fold_const_match_patterns(expr_ty node, PyArena *ctx_, _PyASTPreprocessState *state)
862
2.17k
{
863
2.17k
    if (state->syntax_check_only) {
864
748
        return 1;
865
748
    }
866
1.42k
    switch (node->kind)
867
1.42k
    {
868
35
        case UnaryOp_kind:
869
35
        {
870
35
            if (node->v.UnaryOp.op == USub &&
871
35
                node->v.UnaryOp.operand->kind == Constant_kind)
872
35
            {
873
35
                PyObject *operand = node->v.UnaryOp.operand->v.Constant.value;
874
35
                PyObject *folded = PyNumber_Negative(operand);
875
35
                return make_const(node, folded, ctx_);
876
35
            }
877
0
            break;
878
35
        }
879
5
        case BinOp_kind:
880
5
        {
881
5
            operator_ty op = node->v.BinOp.op;
882
5
            if ((op == Add || op == Sub) &&
883
5
                node->v.BinOp.right->kind == Constant_kind)
884
5
            {
885
5
                CALL(fold_const_match_patterns, expr_ty, node->v.BinOp.left);
886
5
                if (node->v.BinOp.left->kind == Constant_kind) {
887
5
                    PyObject *left = node->v.BinOp.left->v.Constant.value;
888
5
                    PyObject *right = node->v.BinOp.right->v.Constant.value;
889
5
                    PyObject *folded = op == Add ? PyNumber_Add(left, right) : PyNumber_Subtract(left, right);
890
5
                    return make_const(node, folded, ctx_);
891
5
                }
892
5
            }
893
0
            break;
894
5
        }
895
1.38k
        default:
896
1.38k
            break;
897
1.42k
    }
898
1.38k
    return 1;
899
1.42k
}
900
901
static int
902
astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTPreprocessState *state)
903
19.6k
{
904
    // Currently, this is really only used to form complex/negative numeric
905
    // constants in MatchValue and MatchMapping nodes
906
    // We still recurse into all subexpressions and subpatterns anyway
907
19.6k
    ENTER_RECURSIVE();
908
19.6k
    switch (node_->kind) {
909
2.08k
        case MatchValue_kind:
910
2.08k
            CALL(fold_const_match_patterns, expr_ty, node_->v.MatchValue.value);
911
2.08k
            break;
912
689
        case MatchSingleton_kind:
913
689
            break;
914
1.28k
        case MatchSequence_kind:
915
1.28k
            CALL_SEQ(astfold_pattern, pattern, node_->v.MatchSequence.patterns);
916
1.28k
            break;
917
30
        case MatchMapping_kind:
918
30
            CALL_SEQ(fold_const_match_patterns, expr, node_->v.MatchMapping.keys);
919
30
            CALL_SEQ(astfold_pattern, pattern, node_->v.MatchMapping.patterns);
920
30
            break;
921
511
        case MatchClass_kind:
922
511
            CALL(astfold_expr, expr_ty, node_->v.MatchClass.cls);
923
511
            CALL_SEQ(astfold_pattern, pattern, node_->v.MatchClass.patterns);
924
511
            CALL_SEQ(astfold_pattern, pattern, node_->v.MatchClass.kwd_patterns);
925
511
            break;
926
1.83k
        case MatchStar_kind:
927
1.83k
            break;
928
12.1k
        case MatchAs_kind:
929
12.1k
            if (node_->v.MatchAs.pattern) {
930
243
                CALL(astfold_pattern, pattern_ty, node_->v.MatchAs.pattern);
931
243
            }
932
12.1k
            break;
933
12.1k
        case MatchOr_kind:
934
1.08k
            CALL_SEQ(astfold_pattern, pattern, node_->v.MatchOr.patterns);
935
1.08k
            break;
936
    // No default case, so the compiler will emit a warning if new pattern
937
    // kinds are added without being handled here
938
19.6k
    }
939
19.6k
    LEAVE_RECURSIVE();
940
19.6k
    return 1;
941
19.6k
}
942
943
static int
944
astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTPreprocessState *state)
945
1.38k
{
946
1.38k
    CALL(astfold_pattern, expr_ty, node_->pattern);
947
1.38k
    CALL_OPT(astfold_expr, expr_ty, node_->guard);
948
1.38k
    CALL_SEQ(astfold_stmt, stmt, node_->body);
949
1.38k
    return 1;
950
1.38k
}
951
952
static int
953
astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTPreprocessState *state)
954
13.7k
{
955
13.7k
    switch (node_->kind) {
956
13.0k
        case TypeVar_kind:
957
13.0k
            CALL_OPT(astfold_expr, expr_ty, node_->v.TypeVar.bound);
958
13.0k
            CALL_OPT(astfold_expr, expr_ty, node_->v.TypeVar.default_value);
959
13.0k
            break;
960
214
        case ParamSpec_kind:
961
214
            CALL_OPT(astfold_expr, expr_ty, node_->v.ParamSpec.default_value);
962
214
            break;
963
429
        case TypeVarTuple_kind:
964
429
            CALL_OPT(astfold_expr, expr_ty, node_->v.TypeVarTuple.default_value);
965
429
            break;
966
13.7k
    }
967
13.7k
    return 1;
968
13.7k
}
969
970
#undef CALL
971
#undef CALL_OPT
972
#undef CALL_SEQ
973
974
int
975
_PyAST_Preprocess(mod_ty mod, PyArena *arena, PyObject *filename, int optimize,
976
                  int ff_features, int syntax_check_only, int enable_warnings,
977
                  PyObject *module)
978
12.7k
{
979
12.7k
    _PyASTPreprocessState state;
980
12.7k
    memset(&state, 0, sizeof(_PyASTPreprocessState));
981
12.7k
    state.filename = filename;
982
12.7k
    state.module = module;
983
12.7k
    state.optimize = optimize;
984
12.7k
    state.ff_features = ff_features;
985
12.7k
    state.syntax_check_only = syntax_check_only;
986
12.7k
    state.enable_warnings = enable_warnings;
987
12.7k
    if (_Py_CArray_Init(&state.cf_finally, sizeof(ControlFlowInFinallyContext), 20) < 0) {
988
0
        return -1;
989
0
    }
990
991
12.7k
    int ret = astfold_mod(mod, arena, &state);
992
12.7k
    assert(ret || PyErr_Occurred());
993
994
12.7k
    _Py_CArray_Fini(&state.cf_finally);
995
12.7k
    return ret;
996
12.7k
}