Skip to content

Commit 9630cbb

Browse files
committed
Python: test exposed shared SSA adjacency relations
Exercise the three public AdjacentUses relations and compare them with their internal projection or recursive expansion contracts. The cache-placement defect changes evaluator specialization and work rather than semantic results, so a semantic contract snapshot is the stable red-state equivalent; wall-time assertions would be machine-dependent and flaky. This intentionally records no MISSING or SPURIOUS rows: the expected invariant is exact relation equality before and after cache placement changes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 21ab8585-861f-42c9-a834-451604646c6b
1 parent 14bdfd4 commit 9630cbb

3 files changed

Lines changed: 89 additions & 0 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
exposed_first_use_count
2+
| 9 |
3+
exposed_adjacent_use_count
4+
| 1 |
5+
exposed_use_of_def_count
6+
| 10 |
7+
first_use_projection_mismatch_count
8+
| 0 |
9+
adjacent_use_projection_mismatch_count
10+
| 0 |
11+
use_of_def_expansion_mismatch_count
12+
| 0 |
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import python
2+
private import semmle.python.controlflow.internal.AstNodeImpl as CfgImpl
3+
private import semmle.python.controlflow.internal.Cfg as Cfg
4+
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl
5+
6+
private predicate projectedFirstUse(SsaImpl::Definition def, Cfg::NameNode use) {
7+
exists(CfgImpl::BasicBlock bb, int i |
8+
SsaImpl::Impl::firstUse(def, bb, i, _) and
9+
use = bb.getNode(i)
10+
)
11+
}
12+
13+
private predicate projectedAdjacentUse(Cfg::NameNode nodeFrom, Cfg::NameNode nodeTo) {
14+
exists(CfgImpl::BasicBlock bb1, int i1, CfgImpl::BasicBlock bb2, int i2 |
15+
SsaImpl::Impl::adjacentUseUse(bb1, i1, bb2, i2, _, _) and
16+
nodeFrom = bb1.getNode(i1) and
17+
nodeTo = bb2.getNode(i2)
18+
)
19+
}
20+
21+
private predicate expandedUseOfDef(SsaImpl::Definition def, Cfg::NameNode use) {
22+
exists(Cfg::NameNode first |
23+
SsaImpl::AdjacentUses::firstUse(def, first) and
24+
SsaImpl::AdjacentUses::adjacentUseUse*(first, use)
25+
)
26+
}
27+
28+
query int exposed_first_use_count() {
29+
result =
30+
count(SsaImpl::Definition def, Cfg::NameNode use | SsaImpl::AdjacentUses::firstUse(def, use))
31+
}
32+
33+
query int exposed_adjacent_use_count() {
34+
result =
35+
count(Cfg::NameNode nodeFrom, Cfg::NameNode nodeTo |
36+
SsaImpl::AdjacentUses::adjacentUseUse(nodeFrom, nodeTo)
37+
)
38+
}
39+
40+
query int exposed_use_of_def_count() {
41+
result =
42+
count(SsaImpl::Definition def, Cfg::NameNode use | SsaImpl::AdjacentUses::useOfDef(def, use))
43+
}
44+
45+
query int first_use_projection_mismatch_count() {
46+
result =
47+
count(SsaImpl::Definition def, Cfg::NameNode use |
48+
SsaImpl::AdjacentUses::firstUse(def, use) and not projectedFirstUse(def, use)
49+
or
50+
projectedFirstUse(def, use) and not SsaImpl::AdjacentUses::firstUse(def, use)
51+
)
52+
}
53+
54+
query int adjacent_use_projection_mismatch_count() {
55+
result =
56+
count(Cfg::NameNode nodeFrom, Cfg::NameNode nodeTo |
57+
SsaImpl::AdjacentUses::adjacentUseUse(nodeFrom, nodeTo) and
58+
not projectedAdjacentUse(nodeFrom, nodeTo)
59+
or
60+
projectedAdjacentUse(nodeFrom, nodeTo) and
61+
not SsaImpl::AdjacentUses::adjacentUseUse(nodeFrom, nodeTo)
62+
)
63+
}
64+
65+
query int use_of_def_expansion_mismatch_count() {
66+
result =
67+
count(SsaImpl::Definition def, Cfg::NameNode use |
68+
SsaImpl::AdjacentUses::useOfDef(def, use) and not expandedUseOfDef(def, use)
69+
or
70+
expandedUseOfDef(def, use) and not SsaImpl::AdjacentUses::useOfDef(def, use)
71+
)
72+
}

python/ql/test/library-tests/dataflow-new-ssa/test.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ def basic_assign(): # $ def=basic_assign
3131
return y # $ use=y
3232

3333

34+
def repeated_use(x): # $ def=repeated_use def=x
35+
first = x # $ def=first use=x
36+
return x + first # $ use=x use=first
37+
38+
3439
def reassignment(): # $ def=reassignment
3540
x = 1
3641
x = 2 # $ def=x

0 commit comments

Comments
 (0)