Python: simplify TBlockStmt char pred via exclusion list

Replace the 14-disjunct allow-list with a 2-conjunct exclusion list.
Of the 17 Py::StmtList getters in AstGenerated.qll, only Try.getHandlers()
and MatchStmt.getCases() should not be wrapped as BlockStmts (they are
iterated individually by the shared library's Try/Switch logic via
getCatch(int) and getCase(int)). All other StmtLists are imperative
block bodies.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Copilot
2026-05-07 17:13:50 +00:00
parent c9445f74c2
commit b682877968

View File

@@ -35,38 +35,15 @@ module Ast implements AstSig<Py::Location> {
* A synthetic block statement, wrapping a `Py::StmtList`. Each list of
* statements that represents an imperative block (a function/class/module
* body, an `if`/`while`/`for` branch, a `try`/`except`/`finally` body,
* etc.) becomes one `BlockStmt` node in the CFG. Lists used in other
* roles (e.g. `Try.getHandlers()`, which is iterated as catch clauses)
* are excluded.
* etc.) becomes one `BlockStmt` node in the CFG. `Py::StmtList`s used
* in other roles - `Try.getHandlers()` (iterated via `getCatch`) and
* `MatchStmt.getCases()` (iterated via `getCase`) - are excluded, as
* the shared library's `Try`/`Switch` logic walks their items
* individually.
*/
TBlockStmt(Py::StmtList sl) {
sl = any(Py::Scope p).getBody()
or
sl = any(Py::If p).getBody()
or
sl = any(Py::If p).getOrelse()
or
sl = any(Py::While p).getBody()
or
sl = any(Py::While p).getOrelse()
or
sl = any(Py::For p).getBody()
or
sl = any(Py::For p).getOrelse()
or
sl = any(Py::With p).getBody()
or
sl = any(Py::Try p).getBody()
or
sl = any(Py::Try p).getOrelse()
or
sl = any(Py::Try p).getFinalbody()
or
sl = any(Py::Case p).getBody()
or
sl = any(Py::ExceptStmt p).getBody()
or
sl = any(Py::ExceptGroupStmt p).getBody()
not sl = any(Py::Try t).getHandlers() and
not sl = any(Py::MatchStmt m).getCases()
}
/**