From 7fefacd56f5c5ca942e4b1e6ad059a085d3b305d Mon Sep 17 00:00:00 2001 From: Copilot Date: Thu, 7 May 2026 19:33:33 +0000 Subject: [PATCH] Python: introduce TExpr union via newtype-branch alias Mirror the TStmt refactor for the Expr hierarchy: rename the TExpr newtype branch to TPyExpr and add private class TExpr = TPyExpr or TBoolExprPair; This lets the public Expr class use TExpr directly: class Expr extends AstNodeImpl, TExpr { ... } instead of class Expr extends AstNodeImpl { Expr() { this instanceof TExpr or this instanceof TBoolExprPair } ... } 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> --- .../controlflow/internal/AstNodeImpl.qll | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/python/ql/lib/semmle/python/controlflow/internal/AstNodeImpl.qll b/python/ql/lib/semmle/python/controlflow/internal/AstNodeImpl.qll index 2c43802948d..f3ed495bcef 100644 --- a/python/ql/lib/semmle/python/controlflow/internal/AstNodeImpl.qll +++ b/python/ql/lib/semmle/python/controlflow/internal/AstNodeImpl.qll @@ -19,7 +19,7 @@ private import codeql.util.Void module Ast implements AstSig { private newtype TAstNode = TPyStmt(Py::Stmt s) or - TExpr(Py::Expr e) { not e instanceof Py::BoolExpr } or + TPyExpr(Py::Expr e) { not e instanceof Py::BoolExpr } or TScope(Py::Scope sc) or TPattern(Py::Pattern p) or /** @@ -53,6 +53,14 @@ module Ast implements AstSig { */ private class TStmt = TPyStmt or TBlockStmt; + /** + * The union of `TPyExpr` (wrapping non-boolean `Py::Expr`) and + * `TBoolExprPair` (synthetic operand pairs of `and`/`or` expressions). + * Both represent the kinds of node that can appear in an `Expr` + * position in the CFG. + */ + private class TExpr = TPyExpr or TBoolExprPair; + /** * An AST node visible to the shared CFG. * @@ -82,7 +90,7 @@ module Ast implements AstSig { * representation. */ Py::Expr asExpr() { - this = TExpr(result) + this = TPyExpr(result) or this = TBoolExprPair(result, 0) } @@ -159,10 +167,8 @@ module Ast implements AstSig { } /** An expression. */ - class Expr extends AstNodeImpl { - Expr() { this instanceof TExpr or this instanceof TBoolExprPair } - - // For `TExpr` instances, delegate to the wrapped Python expression. + class Expr extends AstNodeImpl, TExpr { + // For `TPyExpr` instances, delegate to the wrapped Python expression. // `BinaryExpr` (the only `TBoolExprPair` subclass) provides its own overrides. override string toString() { result = this.asExpr().toString() }