Skip to content
Merged
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,25 @@ module Public {
*/
LocalVariable asUninitialized() { result = this.(UninitializedNode).getLocalVariable() }

/**
* Gets the uninitialized local variable corresponding to this node behind
* the given levels of indirection, if any.
*/
LocalVariable asIndirectUninitialized(int indirectionIndex) {
exists(IndirectUninitializedNode indirectUninitializedNode |
this = indirectUninitializedNode and
indirectUninitializedNode.getIndirectionIndex() = indirectionIndex
|
result = indirectUninitializedNode.getLocalVariable()
)
}

/**
* Gets the uninitialized local variable corresponding to this node behind
* any levels of indirection, if any.
*/
LocalVariable asIndirectUninitialized() { result = this.asIndirectUninitialized(_) }

/**
* Gets the positional parameter corresponding to the node that represents
* the value of the parameter after `index` number of loads, if any. For
Expand Down Expand Up @@ -761,16 +780,13 @@ module Public {
final override Type getType() { result = this.getPreUpdateNode().getType() }
}

/**
* The value of an uninitialized local variable, viewed as a node in a data
* flow graph.
*/
class UninitializedNode extends Node {
abstract private class AbstractUninitializedNode extends Node {
LocalVariable v;
int indirectionIndex;
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

The class-level doc comment for UninitializedNode now understates the behavior: the implementation no longer represents only indirection level 0. Please update the doc comment to mention that the node can represent different indirection indices (and briefly what 0/1/... mean) so query authors don’t misinterpret it.

This issue also appears on line 784 of the same file.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@MathiasVP MathiasVP Mar 12, 2026

Choose a reason for hiding this comment

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

Copilot is right here. The changes here are actually a semantically breaking change (which would need a full deprecation cycle).

Instead of doing what you have here, I suggest you do what I hinted at on Slack:

  1. Keep the UninitializedNode as it currently is on main
  2. Create a new class IndirectUninitializedNode which basically the the charpred you have here (and indirectionIndex > 1 to avoid overlap with UninitializedNode)
  3. Add a new predicate LocalVariable asIndirectUninitializedNode(int indirectionIndex) on DataFlow::Node and an convenience predicate with 0 parameters LocalVariable asIndirectUninitializedNode() implemented as result = this.asIndirectUninitializedNode(_).

This avoids a breaking change to the UninitializedNode class and the asUninitializedNode predicate.

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.

Addressed in d3066af.


UninitializedNode() {
AbstractUninitializedNode() {
exists(SsaImpl::Definition def, SsaImpl::SourceVariable sv |
def.getIndirectionIndex() = 0 and
def.getIndirectionIndex() = indirectionIndex and
def.getValue().asInstruction() instanceof UninitializedInstruction and
SsaImpl::defToNode(this, def, sv) and
v = sv.getBaseVariable().(SsaImpl::BaseIRVariable).getIRVariable().getAst()
Expand All @@ -781,6 +797,28 @@ module Public {
LocalVariable getLocalVariable() { result = v }
}

/**
* The value of an uninitialized local variable, viewed as a node in a data
* flow graph.
*/
class UninitializedNode extends AbstractUninitializedNode {
UninitializedNode() { indirectionIndex = 0 }
}

/**
* The value of an uninitialized local variable behind one or more levels of
* indirection, viewed as a node in a data flow graph.
*
* NOTE: For the direct value of the uninitialized local variable, see
* `UninitializedNode`.
*/
class IndirectUninitializedNode extends AbstractUninitializedNode {
IndirectUninitializedNode() { indirectionIndex > 0 }

/** Gets the level of indirection to get to this node. */
int getIndirectionIndex() { result = indirectionIndex }
}

/**
* The value of a parameter at function entry, viewed as a node in a data
* flow graph. This includes both explicit parameters such as `x` in `f(x)`
Expand Down
Loading