@@ -15,6 +15,19 @@ private import codeql.controlflow.ControlFlowGraph
1515private import codeql.controlflow.SuccessorType
1616private import codeql.util.Void
1717
18+ /**
19+ * Gets the bound `Name` of a PEP 695 type parameter (`TypeVar`,
20+ * `ParamSpec`, or `TypeVarTuple`). The base `TypeParameter` class does
21+ * not expose `getName()`; this helper dispatches over the subtypes.
22+ */
23+ private Py:: Name typeParameterName ( Py:: TypeParameter tp ) {
24+ result = tp .( Py:: TypeVar ) .getName ( )
25+ or
26+ result = tp .( Py:: ParamSpec ) .getName ( )
27+ or
28+ result = tp .( Py:: TypeVarTuple ) .getName ( )
29+ }
30+
1831/** Provides the Python implementation of the shared CFG `AstSig`. */
1932module Ast implements AstSig< Py:: Location > {
2033 private newtype TAstNode =
@@ -797,6 +810,37 @@ module Ast implements AstSig<Py::Location> {
797810 override AstNode getChild ( int index ) { result = this .getTarget ( index ) }
798811 }
799812
813+ /**
814+ * A PEP 695 `type` statement (`type Alias[T1, T2] = value`).
815+ *
816+ * The type parameters bind at statement-evaluation time. The value
817+ * expression is captured for lazy evaluation but the alias `Name`
818+ * itself binds the resulting `TypeAliasType` object — so the CFG must
819+ * visit at minimum the type-parameter names and the alias name.
820+ */
821+ additional class TypeAliasStmt extends Stmt {
822+ private Py:: TypeAlias ta ;
823+
824+ TypeAliasStmt ( ) { this = TPyStmt ( ta ) }
825+
826+ /** Gets the alias `Name` bound by this statement. */
827+ Expr getName ( ) { result .asExpr ( ) = ta .getName ( ) }
828+
829+ /**
830+ * Gets the `n`th PEP 695 type-parameter name (a `Name` in store
831+ * context), in declaration order.
832+ */
833+ Expr getTypeParamName ( int n ) { result .asExpr ( ) = typeParameterName ( ta .getTypeParameter ( n ) ) }
834+
835+ int getNumberOfTypeParams ( ) { result = count ( ta .getATypeParameter ( ) ) }
836+
837+ override AstNode getChild ( int index ) {
838+ result = this .getTypeParamName ( index )
839+ or
840+ index = this .getNumberOfTypeParams ( ) and result = this .getName ( )
841+ }
842+ }
843+
800844 /** A `try` statement. */
801845 class TryStmt extends Stmt {
802846 private Py:: Try tryStmt ;
@@ -1359,9 +1403,24 @@ module Ast implements AstSig<Py::Location> {
13591403
13601404 ClassDefExpr ( ) { this = TPyExpr ( classExpr ) }
13611405
1406+ /**
1407+ * Gets the `n`th PEP 695 type-parameter name (a `Name` in store
1408+ * context), in declaration order. These bind in the enclosing scope
1409+ * at class-definition time, so the CFG must visit them.
1410+ */
1411+ Expr getTypeParamName ( int n ) {
1412+ result .asExpr ( ) = typeParameterName ( classExpr .getTypeParameter ( n ) )
1413+ }
1414+
1415+ int getNumberOfTypeParams ( ) { result = count ( classExpr .getATypeParameter ( ) ) }
1416+
13621417 Expr getBase ( int n ) { result .asExpr ( ) = classExpr .getBase ( n ) }
13631418
1364- override AstNode getChild ( int index ) { result = this .getBase ( index ) }
1419+ override AstNode getChild ( int index ) {
1420+ result = this .getTypeParamName ( index )
1421+ or
1422+ result = this .getBase ( index - this .getNumberOfTypeParams ( ) )
1423+ }
13651424 }
13661425
13671426 /** A function definition expression (has default args evaluated at definition time). */
@@ -1370,6 +1429,17 @@ module Ast implements AstSig<Py::Location> {
13701429
13711430 FunctionDefExpr ( ) { this = TPyExpr ( funcExpr ) }
13721431
1432+ /**
1433+ * Gets the `n`th PEP 695 type-parameter name (a `Name` in store
1434+ * context), in declaration order. These bind in the enclosing scope
1435+ * at function-definition time, so the CFG must visit them.
1436+ */
1437+ Expr getTypeParamName ( int n ) {
1438+ result .asExpr ( ) = typeParameterName ( funcExpr .getInnerScope ( ) .getTypeParameter ( n ) )
1439+ }
1440+
1441+ int getNumberOfTypeParams ( ) { result = count ( funcExpr .getInnerScope ( ) .getATypeParameter ( ) ) }
1442+
13731443 /**
13741444 * Gets the `n`th default for a positional argument, in evaluation
13751445 * order. Note that `Args.getDefault(int)` is indexed by argument
@@ -1390,9 +1460,11 @@ module Ast implements AstSig<Py::Location> {
13901460 int getNumberOfDefaults ( ) { result = count ( funcExpr .getArgs ( ) .getADefault ( ) ) }
13911461
13921462 override AstNode getChild ( int index ) {
1393- result = this .getDefault ( index )
1463+ result = this .getTypeParamName ( index )
13941464 or
1395- result = this .getKwDefault ( index - this .getNumberOfDefaults ( ) )
1465+ result = this .getDefault ( index - this .getNumberOfTypeParams ( ) )
1466+ or
1467+ result = this .getKwDefault ( index - this .getNumberOfTypeParams ( ) - this .getNumberOfDefaults ( ) )
13961468 }
13971469 }
13981470
0 commit comments