Unify incdec-rhs into the compound-rhs node kind

This commit is contained in:
Owen Mansel-Chan
2026-07-10 23:52:04 +01:00
parent 6bb4aefa4e
commit 8eaa86ea01
7 changed files with 70 additions and 97 deletions

View File

@@ -485,8 +485,6 @@ module GoCfg {
or
n instanceof Go::SendStmt
or
n instanceof Go::IncDecStmt
or
n instanceof Go::FuncDecl
}
@@ -543,8 +541,10 @@ module GoCfg {
tag = "zero-init:" + i.toString()
)
or
// Increment/decrement implicit right-hand side (the `operand + 1` value)
n instanceof Go::IncDecStmt and tag = "incdec-rhs"
// Increment/decrement: a single node computes `operand + 1` (or `- 1`)
// and writes it back, modelled the same as a compound assignment's
// `compound-rhs` node (see `IR::EvalCompoundAssignRhsInstruction`).
n instanceof Go::IncDecStmt and tag = "compound-rhs"
or
// Result write nodes in return statements
exists(int i, Go::ReturnStmt ret |
@@ -1154,26 +1154,23 @@ module GoCfg {
}
/**
* Increment/decrement: operand → incdec-rhs → In(stmt)
* (IncDecStmt is in postOrInOrder, so In(stmt) is its evaluation point)
* Increment/decrement: operand → compound-rhs → After(stmt).
*
* The implicit constant `1` operand of the `operand + 1` computation is
* modelled directly on the `incdec-rhs` instruction rather than as its own
* control-flow node.
* `x++` is modelled just like the compound assignment `x += 1`: a single
* `compound-rhs` node computes the updated value and writes it back to the
* operand (see `IR::EvalCompoundAssignRhsInstruction`). The implicit constant
* `1` is modelled directly on that node rather than as its own node.
*/
private predicate incDecStep(PreControlFlowNode n1, PreControlFlowNode n2) {
exists(Go::IncDecStmt s |
// Before → Before operand
n1.isBefore(s) and n2.isBefore(s.getOperand())
or
// After operand → incdec-rhs
n1.isAfter(s.getOperand()) and n2.isAdditional(s, "incdec-rhs")
// After operand → compound-rhs (the update value + write)
n1.isAfter(s.getOperand()) and n2.isAdditional(s, "compound-rhs")
or
// incdec-rhs → In(stmt) (the assignment itself)
n1.isAdditional(s, "incdec-rhs") and n2.isIn(s)
or
// In(stmt) → After(stmt)
n1.isIn(s) and n2.isAfter(s)
// compound-rhs → After(stmt)
n1.isAdditional(s, "compound-rhs") and n2.isAfter(s)
)
}

View File

@@ -176,11 +176,6 @@ module IR {
or
this instanceof ConditionGuardInstruction and result = "condition guard"
or
this instanceof IncDecInstruction and result = "increment/decrement"
or
this instanceof EvalIncDecRhsInstruction and
result = "right-hand side of increment/decrement"
or
this instanceof ReturnInstruction and result = "return"
or
this instanceof WriteResultInstruction and result = "result write"
@@ -665,23 +660,36 @@ module IR {
}
/**
* An instruction that computes the (implicit) right-hand side of a compound assignment,
* such as the `x + y` in `x += y`, and writes the resulting value to the assignment's
* left-hand side.
* An instruction that computes the (implicit) right-hand side of a compound
* assignment (the `x + y` in `x += y`) or an increment/decrement (the
* `x + 1` in `x++`), and writes the resulting value to the left-hand side.
*/
class EvalCompoundAssignRhsInstruction extends WriteInstruction {
CompoundAssignStmt assgn;
AstNode s;
EvalCompoundAssignRhsInstruction() { this.isAdditional(assgn, "compound-rhs") }
EvalCompoundAssignRhsInstruction() {
this.isAdditional(s, "compound-rhs") and
(s instanceof CompoundAssignStmt or s instanceof IncDecStmt)
}
/** Gets the corresponding compound assignment statement. */
CompoundAssignStmt getAssignment() { result = assgn }
/** Gets the corresponding compound assignment statement, if it is one. */
CompoundAssignStmt getAssignment() { result = s }
/**
* Gets the corresponding compound assignment (`x += y`) or increment/decrement
* (`x++`, `x--`) statement.
*/
AstNode getStmt() { result = s }
override Instruction getRhs() { result = this }
override Type getResultType() { result = assgn.getRhs().getType() }
override Type getResultType() {
result = s.(CompoundAssignStmt).getRhs().getType()
or
result = s.(IncDecStmt).getOperand().getType()
}
override ControlFlow::Root getRoot() { result.isRootOf(assgn) }
override ControlFlow::Root getRoot() { result.isRootOf(s) }
}
/** An instruction extracting a component of a tuple value. */
@@ -871,36 +879,6 @@ module IR {
override ControlFlow::Root getRoot() { result.isRootOf(go) }
}
/** An instruction that corresponds to an increment or decrement statement. */
class IncDecInstruction extends WriteInstruction {
IncDecStmt ids;
IncDecInstruction() { this.isIn(ids) }
override Instruction getRhs() {
result.(EvalIncDecRhsInstruction).isAdditional(ids, "incdec-rhs")
}
override ControlFlow::Root getRoot() { result.isRootOf(ids) }
}
/**
* An instruction that computes the (implicit) right-hand side of an increment or
* decrement statement.
*/
class EvalIncDecRhsInstruction extends Instruction {
IncDecStmt ids;
EvalIncDecRhsInstruction() { this.isAdditional(ids, "incdec-rhs") }
/** Gets the corresponding increment or decrement statement. */
IncDecStmt getStmt() { result = ids }
override Type getResultType() { result = ids.getOperand().getType() }
override ControlFlow::Root getRoot() { result.isRootOf(ids) }
}
/** An instruction corresponding to a return from a function. */
class ReturnInstruction extends Instruction {
ReturnStmt ret;
@@ -1104,12 +1082,14 @@ module IR {
)
)
or
exists(IncDecStmt ids | write.isIn(ids) | lhs = ids.getOperand().stripParens())
or
exists(CompoundAssignStmt ca | write.isAdditional(ca, "compound-rhs") |
lhs = ca.getLhs().stripParens()
)
or
exists(IncDecStmt ids | write.isAdditional(ids, "compound-rhs") |
lhs = ids.getOperand().stripParens()
)
or
exists(FuncDef fd, int idx |
write.isAdditional(fd.getBody(), "param-init:" + idx.toString()) and
lhs = fd.getParameter(idx).getDeclaration()

View File

@@ -389,12 +389,13 @@ float getAnSsaUpperBound(SsaDefinition def) {
)
else
//SSA definition corresponding to an `IncDecStmt`
if explicitDef.getInstruction() instanceof IR::IncDecInstruction
if
explicitDef.getInstruction().(IR::EvalCompoundAssignRhsInstruction).getStmt() instanceof
IncDecStmt
then
exists(IncDecStmt incOrDec, IR::IncDecInstruction instr, float exprLB |
instr = explicitDef.getInstruction() and
exists(IncDecStmt incOrDec, float exprLB |
explicitDef.getInstruction().(IR::EvalCompoundAssignRhsInstruction).getStmt() = incOrDec and
exprLB = getAnUpperBound(incOrDec.getOperand()) and
instr.getRhs().(IR::EvalIncDecRhsInstruction).getStmt() = incOrDec and
(
//IncStmt(x++)
exists(IncStmt inc |
@@ -475,12 +476,13 @@ float getAnSsaLowerBound(SsaDefinition def) {
)
else
//IncDecStmt
if explicitDef.getInstruction() instanceof IR::IncDecInstruction
if
explicitDef.getInstruction().(IR::EvalCompoundAssignRhsInstruction).getStmt() instanceof
IncDecStmt
then
exists(IncDecStmt incOrDec, IR::IncDecInstruction instr, float exprLB |
instr = explicitDef.getInstruction() and
exists(IncDecStmt incOrDec, float exprLB |
explicitDef.getInstruction().(IR::EvalCompoundAssignRhsInstruction).getStmt() = incOrDec and
exprLB = getALowerBound(incOrDec.getOperand()) and
instr.getRhs().(IR::EvalIncDecRhsInstruction).getStmt() = incOrDec and
(
//IncStmt(x++)
exists(IncStmt inc |
@@ -550,9 +552,7 @@ predicate ssaDependsOnSsa(SsaDefinition nextDef, SsaDefinition prevDef) {
nextDef
.(SsaExplicitDefinition)
.getInstruction()
.(IR::IncDecInstruction)
.getRhs()
.(IR::EvalIncDecRhsInstruction)
.(IR::EvalCompoundAssignRhsInstruction)
.getStmt() = incDec and
ssaDependsOnExpr(prevDef, incDec.getOperand())
)

View File

@@ -1279,7 +1279,7 @@
| exprs.go:49:30:54:1 | result-read:0 block statement | exprs.go:49:1:54:1 | Normal Exit |
| exprs.go:49:30:54:1 | zero-init:0 block statement | exprs.go:50:2:52:2 | for statement |
| exprs.go:50:2:52:2 | After for statement | exprs.go:53:2:53:7 | Before return statement |
| exprs.go:50:2:52:2 | [LoopHeader] for statement | exprs.go:50:27:50:29 | Before increment statement |
| exprs.go:50:2:52:2 | [LoopHeader] for statement | exprs.go:50:27:50:29 | increment statement |
| exprs.go:50:2:52:2 | for statement | exprs.go:50:6:50:11 | ... := ... |
| exprs.go:50:6:50:11 | ... := ... | exprs.go:50:11:50:11 | Before 0 |
| exprs.go:50:6:50:11 | After ... := ... | exprs.go:50:14:50:24 | Before ...<... |
@@ -1304,13 +1304,12 @@
| exprs.go:50:22:50:23 | After xs | exprs.go:50:18:50:24 | call to len |
| exprs.go:50:22:50:23 | Before xs | exprs.go:50:22:50:23 | xs |
| exprs.go:50:22:50:23 | xs | exprs.go:50:22:50:23 | After xs |
| exprs.go:50:27:50:27 | After i | exprs.go:50:27:50:29 | incdec-rhs increment statement |
| exprs.go:50:27:50:27 | After i | exprs.go:50:27:50:29 | compound-rhs increment statement |
| exprs.go:50:27:50:27 | Before i | exprs.go:50:27:50:27 | i |
| exprs.go:50:27:50:27 | i | exprs.go:50:27:50:27 | After i |
| exprs.go:50:27:50:29 | After increment statement | exprs.go:50:14:50:24 | Before ...<... |
| exprs.go:50:27:50:29 | Before increment statement | exprs.go:50:27:50:27 | Before i |
| exprs.go:50:27:50:29 | incdec-rhs increment statement | exprs.go:50:27:50:29 | increment statement |
| exprs.go:50:27:50:29 | increment statement | exprs.go:50:27:50:29 | After increment statement |
| exprs.go:50:27:50:29 | compound-rhs increment statement | exprs.go:50:27:50:29 | After increment statement |
| exprs.go:50:27:50:29 | increment statement | exprs.go:50:27:50:27 | Before i |
| exprs.go:50:31:52:2 | After block statement | exprs.go:50:2:52:2 | [LoopHeader] for statement |
| exprs.go:50:31:52:2 | block statement | exprs.go:51:3:51:14 | ... += ... |
| exprs.go:51:3:51:5 | After res | exprs.go:51:10:51:14 | Before index expression |
@@ -2235,7 +2234,7 @@
| main.go:73:7:73:7 | After 1 | main.go:73:2:73:7 | assign:0 ... := ... |
| main.go:73:7:73:7 | Before 1 | main.go:73:7:73:7 | 1 |
| main.go:74:2:79:2 | After for statement | main.go:80:2:80:13 | expression statement |
| main.go:74:2:79:2 | [LoopHeader] for statement | main.go:74:16:74:18 | Before increment statement |
| main.go:74:2:79:2 | [LoopHeader] for statement | main.go:74:16:74:18 | increment statement |
| main.go:74:2:79:2 | for statement | main.go:74:6:74:11 | ... := ... |
| main.go:74:6:74:11 | ... := ... | main.go:74:11:74:11 | Before 0 |
| main.go:74:6:74:11 | After ... := ... | main.go:74:20:79:2 | block statement |
@@ -2243,13 +2242,12 @@
| main.go:74:11:74:11 | 0 | main.go:74:11:74:11 | After 0 |
| main.go:74:11:74:11 | After 0 | main.go:74:6:74:11 | assign:0 ... := ... |
| main.go:74:11:74:11 | Before 0 | main.go:74:11:74:11 | 0 |
| main.go:74:16:74:16 | After i | main.go:74:16:74:18 | incdec-rhs increment statement |
| main.go:74:16:74:16 | After i | main.go:74:16:74:18 | compound-rhs increment statement |
| main.go:74:16:74:16 | Before i | main.go:74:16:74:16 | i |
| main.go:74:16:74:16 | i | main.go:74:16:74:16 | After i |
| main.go:74:16:74:18 | After increment statement | main.go:74:20:79:2 | block statement |
| main.go:74:16:74:18 | Before increment statement | main.go:74:16:74:16 | Before i |
| main.go:74:16:74:18 | incdec-rhs increment statement | main.go:74:16:74:18 | increment statement |
| main.go:74:16:74:18 | increment statement | main.go:74:16:74:18 | After increment statement |
| main.go:74:16:74:18 | compound-rhs increment statement | main.go:74:16:74:18 | After increment statement |
| main.go:74:16:74:18 | increment statement | main.go:74:16:74:16 | Before i |
| main.go:74:20:79:2 | After block statement | main.go:74:2:79:2 | [LoopHeader] for statement |
| main.go:74:20:79:2 | block statement | main.go:75:3:77:3 | if statement |
| main.go:75:3:77:3 | After if statement | main.go:78:3:78:7 | ... = ... |
@@ -2291,7 +2289,7 @@
| main.go:82:7:82:7 | After 1 | main.go:82:2:82:7 | assign:0 ... := ... |
| main.go:82:7:82:7 | Before 1 | main.go:82:7:82:7 | 1 |
| main.go:83:2:88:2 | After for statement | main.go:89:2:89:13 | expression statement |
| main.go:83:2:88:2 | [LoopHeader] for statement | main.go:83:16:83:18 | Before increment statement |
| main.go:83:2:88:2 | [LoopHeader] for statement | main.go:83:16:83:18 | increment statement |
| main.go:83:2:88:2 | for statement | main.go:83:6:83:11 | ... := ... |
| main.go:83:6:83:11 | ... := ... | main.go:83:11:83:11 | Before 0 |
| main.go:83:6:83:11 | After ... := ... | main.go:83:20:88:2 | block statement |
@@ -2299,13 +2297,12 @@
| main.go:83:11:83:11 | 0 | main.go:83:11:83:11 | After 0 |
| main.go:83:11:83:11 | After 0 | main.go:83:6:83:11 | assign:0 ... := ... |
| main.go:83:11:83:11 | Before 0 | main.go:83:11:83:11 | 0 |
| main.go:83:16:83:16 | After i | main.go:83:16:83:18 | incdec-rhs increment statement |
| main.go:83:16:83:16 | After i | main.go:83:16:83:18 | compound-rhs increment statement |
| main.go:83:16:83:16 | Before i | main.go:83:16:83:16 | i |
| main.go:83:16:83:16 | i | main.go:83:16:83:16 | After i |
| main.go:83:16:83:18 | After increment statement | main.go:83:20:88:2 | block statement |
| main.go:83:16:83:18 | Before increment statement | main.go:83:16:83:16 | Before i |
| main.go:83:16:83:18 | incdec-rhs increment statement | main.go:83:16:83:18 | increment statement |
| main.go:83:16:83:18 | increment statement | main.go:83:16:83:18 | After increment statement |
| main.go:83:16:83:18 | compound-rhs increment statement | main.go:83:16:83:18 | After increment statement |
| main.go:83:16:83:18 | increment statement | main.go:83:16:83:16 | Before i |
| main.go:83:20:88:2 | After block statement | main.go:83:2:88:2 | [LoopHeader] for statement |
| main.go:83:20:88:2 | block statement | main.go:84:3:84:7 | ... = ... |
| main.go:84:3:84:7 | ... = ... | main.go:84:7:84:7 | Before 2 |
@@ -3160,7 +3157,7 @@
| stmts.go:23:11:37:2 | After block statement | stmts.go:23:2:37:2 | [LoopHeader] for statement |
| stmts.go:23:11:37:2 | block statement | stmts.go:24:3:36:3 | for statement |
| stmts.go:24:3:36:3 | After for statement | stmts.go:23:11:37:2 | After block statement |
| stmts.go:24:3:36:3 | [LoopHeader] for statement | stmts.go:24:23:24:25 | Before increment statement |
| stmts.go:24:3:36:3 | [LoopHeader] for statement | stmts.go:24:23:24:25 | increment statement |
| stmts.go:24:3:36:3 | for statement | stmts.go:24:7:24:12 | ... := ... |
| stmts.go:24:7:24:12 | ... := ... | stmts.go:24:12:24:12 | Before 0 |
| stmts.go:24:7:24:12 | After ... := ... | stmts.go:24:15:24:20 | Before ...<... |
@@ -3179,13 +3176,12 @@
| stmts.go:24:19:24:20 | 10 | stmts.go:24:19:24:20 | After 10 |
| stmts.go:24:19:24:20 | After 10 | stmts.go:24:15:24:20 | ...<... |
| stmts.go:24:19:24:20 | Before 10 | stmts.go:24:19:24:20 | 10 |
| stmts.go:24:23:24:23 | After i | stmts.go:24:23:24:25 | incdec-rhs increment statement |
| stmts.go:24:23:24:23 | After i | stmts.go:24:23:24:25 | compound-rhs increment statement |
| stmts.go:24:23:24:23 | Before i | stmts.go:24:23:24:23 | i |
| stmts.go:24:23:24:23 | i | stmts.go:24:23:24:23 | After i |
| stmts.go:24:23:24:25 | After increment statement | stmts.go:24:15:24:20 | Before ...<... |
| stmts.go:24:23:24:25 | Before increment statement | stmts.go:24:23:24:23 | Before i |
| stmts.go:24:23:24:25 | incdec-rhs increment statement | stmts.go:24:23:24:25 | increment statement |
| stmts.go:24:23:24:25 | increment statement | stmts.go:24:23:24:25 | After increment statement |
| stmts.go:24:23:24:25 | compound-rhs increment statement | stmts.go:24:23:24:25 | After increment statement |
| stmts.go:24:23:24:25 | increment statement | stmts.go:24:23:24:23 | Before i |
| stmts.go:24:27:36:3 | block statement | stmts.go:25:4:35:4 | if statement |
| stmts.go:25:4:35:4 | if statement | stmts.go:25:7:25:16 | ... := ... |
| stmts.go:25:7:25:16 | ... := ... | stmts.go:25:12:25:16 | Before ...-... |

View File

@@ -20,7 +20,7 @@
| main.go:15:9:15:9 | 0 | main.go:15:2:15:9 | SSA def(acc) |
| main.go:16:9:19:2 | SSA def(acc) | main.go:17:3:17:5 | acc |
| main.go:17:3:17:7 | SSA def(acc) | main.go:18:10:18:12 | acc |
| main.go:17:3:17:7 | incdec-rhs increment statement | main.go:17:3:17:7 | SSA def(acc) |
| main.go:17:3:17:7 | compound-rhs increment statement | main.go:17:3:17:7 | SSA def(acc) |
| main.go:22:42:31:1 | SSA def(b) | main.go:23:5:23:5 | b |
| main.go:22:42:31:1 | SSA def(x) | main.go:24:10:24:10 | x |
| main.go:22:42:31:1 | SSA def(x) | main.go:26:11:26:11 | x |

View File

@@ -16,7 +16,7 @@
| result 1 | main.go:35:1:38:1 | function declaration | main.go:35:29:38:1 | zero-init:1 block statement |
| result 1 | main.go:35:1:38:1 | function declaration | main.go:36:9:36:10 | 42 |
| result 1 | main.go:40:1:48:1 | function declaration | main.go:40:33:48:1 | zero-init:1 block statement |
| result 1 | main.go:40:1:48:1 | function declaration | main.go:42:3:42:5 | incdec-rhs increment statement |
| result 1 | main.go:40:1:48:1 | function declaration | main.go:42:3:42:5 | compound-rhs increment statement |
| result 1 | main.go:40:1:48:1 | function declaration | main.go:45:13:45:13 | 1 |
| result 1 | main.go:40:1:48:1 | function declaration | main.go:47:12:47:12 | 4 |
| result 1 | tst2.go:8:1:12:1 | function declaration | tst2.go:11:12:11:14 | err |

View File

@@ -17,11 +17,11 @@
| main.go:59:3:59:7 | assign:0 ... = ... | main.go:57:6:57:6 | x | main.go:59:7:59:7 | 2 |
| main.go:63:2:63:7 | assign:0 ... := ... | main.go:63:2:63:2 | y | main.go:63:7:63:7 | 1 |
| main.go:64:6:64:11 | assign:0 ... := ... | main.go:64:6:64:6 | i | main.go:64:11:64:11 | 0 |
| main.go:64:16:64:18 | increment statement | main.go:64:6:64:6 | i | main.go:64:16:64:18 | incdec-rhs increment statement |
| main.go:64:16:64:18 | compound-rhs increment statement | main.go:64:6:64:6 | i | main.go:64:16:64:18 | compound-rhs increment statement |
| main.go:68:3:68:7 | assign:0 ... = ... | main.go:63:2:63:2 | y | main.go:68:7:68:7 | 2 |
| main.go:72:2:72:7 | assign:0 ... := ... | main.go:72:2:72:2 | z | main.go:72:7:72:7 | 1 |
| main.go:73:6:73:11 | assign:0 ... := ... | main.go:73:6:73:6 | i | main.go:73:11:73:11 | 0 |
| main.go:73:16:73:18 | increment statement | main.go:73:6:73:6 | i | main.go:73:16:73:18 | incdec-rhs increment statement |
| main.go:73:16:73:18 | compound-rhs increment statement | main.go:73:6:73:6 | i | main.go:73:16:73:18 | compound-rhs increment statement |
| main.go:74:3:74:7 | assign:0 ... = ... | main.go:72:2:72:2 | z | main.go:74:7:74:7 | 2 |
| main.go:82:36:86:1 | zero-init:0 block statement | main.go:82:18:82:18 | a | main.go:82:36:86:1 | zero-init:0 block statement |
| main.go:82:36:86:1 | zero-init:1 block statement | main.go:82:25:82:25 | b | main.go:82:36:86:1 | zero-init:1 block statement |