Skip to content

SSA: Split reads in MakeSsa based on explicit/implicit instead of certain/uncertain. - #23071

Open
aschackmull wants to merge 1 commit into
github:mainfrom
aschackmull:ssa/makessa-reads
Open

aschackmull wants to merge 1 commit into
github:mainfrom
aschackmull:ssa/makessa-reads

Conversation

@aschackmull

Copy link
Copy Markdown
Contributor

The Expr getARead() member predicate on SsaDefinition doesn't make sense for implicit reads, and those implicit reads aren't very relevant in the contexts where expression-based SSA reasoning is used (e.g. guards logic, range analysis, or query-specific SSA usage). At the same time, implicit reads can be very relevant for DataFlowIntegration (e.g. this-flow), so the certain/uncertain split isn't appropriate in MakeSsa (and has been blocking adoption in Go and Unified). The straightforward fix is to make the explicit/implicit split explicit in the MakeSsa instantiation.

@aschackmull aschackmull added the no-change-note-required This PR does not need a change note label Nov 10, 2026
@aschackmull
aschackmull requested review from a team as code owners November 10, 2026 10:40
Copilot AI auto review requested due to automatic review settings November 10, 2026 10:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

There are no active review issues for the change separating explicit and implicit SSA reads.

No open issues 🎉

What changed in this PR

This PR changes the shared SSA API to distinguish explicit and implicit reads instead of certain and uncertain reads. This keeps expression-based SSA reasoning focused on explicit reads while retaining implicit reads for data-flow integration.

Changes:

  • Add an explicitRead input predicate and use it to classify reads in MakeSsa.
  • Update Java and C# SSA adapters to identify explicit reads.
  • Migrate Java capture handling to ssaDefReachesImplicitRead.
File Description
shared/​ssa/​codeql/​ssa/​Ssa.qll Define explicit reads, update reaching-read predicates, and clarify explicit-write documentation.
java/​ql/​lib/​semmle/​code/​java/​dataflow/​internal/​SsaImpl.qll Identify explicit variable reads and migrate capture handling.
java/​ql/​lib/​semmle/​code/​java/​dataflow/​internal/​BaseSSA.qll Apply the explicit-read contract and capture API to base SSA.
csharp/​ql/​lib/​semmle/​code/​csharp/​dataflow/​internal/​SsaImpl.qll Identify explicit reads through assignable accesses.
csharp/​ql/​lib/​semmle/​code/​csharp/​dataflow/​internal/​BaseSSA.qll Identify explicit reads by their target variable.

Review effort: Balanced (auto)

* Holds if `e` reads the value of `v`. These are the reads that are
* included in the `SsaDefinition.getARead()` member predicate.
*/
predicate explicitRead(Expr e, SourceVariable v);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When is not the same as

predicate explicitRead(Expr e, SourceVariable v) {
    exists(BasicBlock bb, int i |
      variableRead(bb, i, v, true) and
      e.getControlFlowNode() = bb.getNode(i)
    )
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole point of the PR is to be able to distinguish the two. If we merely use variableRead(bb, i, v, true) and e.getControlFlowNode() = bb.getNode(i) then we make the assumption that the expression implies the variable - and furthermore, in this context we assume that the expression is the variable read. This is true for explicit reads where the expression is a concrete read of a specific variable, but there are several cases where we have certain reads (4th column = true in variableRead) that are implicit, so the expression at the cfg node of the read isn't the actual variable read. E.g. implicit this/self, which is tracked as an SSA variable in unified. Also, Go functions have an epilogue where return variables are implicitly read. These are reads that should have certain = true because they should be included in the data flow integration, but they should not be included in SsaVariable.getARead(), since that returns an expression that's assumed to equal the read.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C# Java no-change-note-required This PR does not need a change note

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants