Skip to content

Shared CFG: add defaulted getWhileElse/getForeachElse to AstSig#21931

Open
yoff wants to merge 1 commit into
mainfrom
yoff/python-shared-cfg-loop-else
Open

Shared CFG: add defaulted getWhileElse/getForeachElse to AstSig#21931
yoff wants to merge 1 commit into
mainfrom
yoff/python-shared-cfg-loop-else

Conversation

@yoff
Copy link
Copy Markdown
Contributor

@yoff yoff commented Jun 2, 2026

Lifts the shared-controlflow changes out of #21921 so they can be reviewed independently. No behavioural change for existing languages (Java, C#, Ruby, Swift, Go, …) — both new predicates default to none() and the Make0 loop-edge case extensions only fire when a language overrides them.

Motivation

Python's upcoming new CFG library (#21921) needs to model while-else / for-else, where the else block runs when the loop condition becomes false (rather than via a break). The shared CFG didn't previously have predicates exposing those else blocks.

Changes

  • Adds defaulted getWhileElse(WhileStmt) and getForeachElse(ForeachStmt) to AstSig (shared/controlflow/codeql/controlflow/ControlFlowGraph.qll).
  • Extends Make0 in three places (while exit, foreach empty-collection exit, foreach post-body exit) to route through the else block if one exists.

Verification

Lifts the shared-controlflow changes out of the larger Python new-CFG
PR so they can be reviewed independently. No behavioural change for
existing languages (Java, C#, Ruby, Swift, Go, ...) — both new
predicates default to `none()` and the Make0 loop-edge case
extensions only fire when a language overrides them.

Python's upcoming AstNodeImpl wiring uses these predicates to model
`while-else` and `for-else`, where the `else` block runs when the
loop condition becomes false (rather than via a `break`).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 2, 2026 13:48
@yoff yoff requested a review from a team as a code owner June 2, 2026 13:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds shared-CFG signature hooks for loop else blocks so languages that support while-else / for-else (notably Python) can expose that structure to the shared control-flow graph without impacting existing languages.

Changes:

  • Added defaulted AstSig.getWhileElse(WhileStmt) and AstSig.getForeachElse(ForeachStmt) predicates (default none()).
  • Updated shared CFG construction (Make0) to route certain loop-exit edges through an else block when provided by a language implementation.
  • Added a shared/controlflow change note documenting the new signature predicates.
Show a summary per file
File Description
shared/controlflow/codeql/controlflow/ControlFlowGraph.qll Extends the shared CFG AST signature with defaulted loop-else accessors and threads them into loop edge construction.
shared/controlflow/change-notes/2026-05-19-loop-else.md Documents the new defaulted AstSig predicates for loop else blocks.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 1

---
category: feature
---
* The `AstSig` signature gains two new defaulted predicates `getWhileElse` and `getForeachElse`, allowing languages (like Python) to model `while-else` / `for-else` constructs where the `else` branch is taken when the loop condition becomes false (rather than via a `break`). Existing languages that do not provide these predicates retain the previous behaviour.
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.

I wouldn't add a change note. This isn't a user-facing change.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants