Files
codeql/python/ql/test/library-tests/dataflow-new-ssa/test.py
Copilot 5863545eae Python: add new shared-SSA-backed SSA adapter
Preparatory refactor for the shared-CFG dataflow migration. Adds the
new Python SSA adapter additively, without changing any production
behaviour.

Library additions:

- semmle.python.dataflow.new.internal.SsaImpl — Python SSA
  implementation built on the new (shared) CFG. Mirrors the Java SSA
  adapter (java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll):
  an InputSig is defined in terms of positional (BasicBlock, int)
  variable references, and the shared
  codeql.ssa.Ssa::Make<Location, Cfg, Input> module is then
  instantiated.

  SourceVariable is the AST-level Py::Variable. Variable references
  are looked up via the new CFG facade's NameNode.defines/uses/deletes
  predicates (added in the preceding PR), which themselves are
  one-line bridges to AST-level Name.defines/uses/deletes.

  Implicit-entry definitions are inserted for non-local/global/builtin
  reads, captured variables, and (when needed) parameters.

Test additions:

- library-tests/dataflow-new-ssa/ — exercises the new SSA over a
  representative test corpus and checks expected def/use chains.

- library-tests/dataflow-new-ssa-vs-legacy/ — runs both new SSA and
  legacy ESSA over the same corpus and diffs the results, so any
  semantic divergence shows up as a test failure.

Production impact:

None. The new SSA adapter has zero callers in lib/ and src/ — the
legacy ESSA SSA (semmle/python/essa/*) remains the default. The
dataflow library is not migrated yet; that lands in a follow-up PR.

Verified by:
- All 367 lib + src + consistency-queries compile clean.
- All 641 ControlFlow + PointsTo + dataflow + essa + consistency
  library-tests pass.
- Both new dataflow-new-ssa[/vs-legacy] test packs pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-29 19:37:18 +00:00

49 lines
1.4 KiB
Python

# Basic SSA tests for the new-CFG SSA adapter.
#
# The shared SSA implementation prunes its construction by liveness:
# definitions of variables that are not read are never materialised.
# This is by design — write-only variables would only bloat the SSA
# graph. Tests therefore must always include a read of each variable
# being verified.
#
# Annotations:
# def=<var>: there is an SSA write definition of <var> at this line
# use=<var>: <var> is used here and the read resolves to some def
#
# Note: a module-level `def name(...)` statement is itself a write
# definition of the module global `name`, which is live (it can be read
# externally), so every function below carries a `def=<name>` annotation
# on its `def` line.
def basic_param(x): # $ def=basic_param def=x
return x # $ use=x
def basic_assign(): # $ def=basic_assign
y = 1 # $ def=y
return y # $ use=y
def reassignment(): # $ def=reassignment
x = 1
x = 2 # $ def=x
return x # $ use=x
def if_else_phi(cond): # $ def=if_else_phi def=cond
if cond: # $ use=cond phi=x
x = 1 # $ def=x
else:
x = 2 # $ def=x
return x # $ use=x
# `some_undefined` is never assigned anywhere, so (matching legacy ESSA)
# the SSA library creates no entry definition for it: an undefined-name
# read resolves to no SSA def, hence there is no `use=` here.
def use_global(): # $ def=use_global
return some_undefined