Fold uninitialised var-decl zero-init and write into one node

This commit is contained in:
Owen Mansel-Chan
2026-07-10 17:03:53 +01:00
parent 1c60ffa3a7
commit d30162b2ca
4 changed files with 52 additions and 25 deletions

View File

@@ -508,7 +508,11 @@ module GoCfg {
// so the guard itself emits no assignment write node.
not n = any(Go::TypeSwitchStmt ts).getAssign()
or
notBlankIdent(n.(Go::ValueSpec).getNameExpr(i))
// A `ValueSpec` without an initializer is written by its `zero-init`
// node directly (see `IR::InitVariableInstruction`), so only specs
// *with* an initializer emit an `assign` write node.
notBlankIdent(n.(Go::ValueSpec).getNameExpr(i)) and
exists(n.(Go::ValueSpec).getAnInit())
or
notBlankIdent(n.(Go::RangeElementExpr).getKey()) and i = 0
or
@@ -1103,7 +1107,10 @@ module GoCfg {
// above, so they emit no separate `assign:j` node.
not assgn instanceof Go::CompoundAssignStmt
or
notBlankIdent(assgn.(Go::ValueSpec).getNameExpr(j))
// A `ValueSpec` without an initializer is written by its `zero-init`
// node directly, so only specs *with* an initializer emit `assign:j`.
notBlankIdent(assgn.(Go::ValueSpec).getNameExpr(j)) and
exists(assgn.(Go::ValueSpec).getAnInit())
or
notBlankIdent(assgn.(Go::RangeElementExpr).getKey()) and j = 0
or

View File

@@ -641,7 +641,11 @@ module IR {
(
exists(assgn.(Assignment).getLhs(i))
or
exists(assgn.(ValueSpec).getNameExpr(i))
// A `ValueSpec` without an initializer (`var x int`) is written by its
// `zero-init` node directly (see `InitVariableInstruction`), so only
// specs *with* an initializer produce an `assign` node.
exists(assgn.(ValueSpec).getNameExpr(i)) and
exists(assgn.(ValueSpec).getAnInit())
or
assgn instanceof RangeElementExpr and i in [0, 1]
)
@@ -656,9 +660,6 @@ module IR {
exists(ValueSpec spec | spec = assgn |
spec.getNumName() = spec.getNumInit() and
result = evalExprInstruction(spec.getInit(i))
or
result =
implicitInitInstruction(any(ValueEntity v | spec.getNameExpr(i) = v.getDeclaration()))
)
or
result.(ExtractTupleElementInstruction).isAdditional(assgn, "extract:" + i.toString())
@@ -1005,6 +1006,28 @@ module IR {
override ControlFlow::Root getRoot() { result = res.getFunction() }
}
/**
* An instruction initializing a variable declared without an initializer
* (`var x int`) to its zero value.
*
* This is the same node as the `EvalImplicitInitInstruction` that computes the
* zero value: the zero-value instruction performs the write of the variable
* directly, rather than feeding a separate write node.
*/
class InitVariableInstruction extends WriteInstruction {
ValueSpec spec;
int idx;
InitVariableInstruction() {
this.isAdditional(spec, "zero-init:" + idx.toString()) and
exists(spec.getNameExpr(idx))
}
override Instruction getRhs() { result = this }
override ControlFlow::Root getRoot() { result.isRootOf(spec) }
}
/** An instruction that gets the next key-value pair in a range loop. */
class GetNextEntryInstruction extends Instruction {
RangeElementExpr p;
@@ -1123,6 +1146,11 @@ module IR {
write.isAdditional(fd.getBody(), "result-zero-init:" + idx.toString()) and
lhs = fd.getResultVar(idx).getDeclaration()
)
or
exists(ValueSpec spec, int idx |
write.isAdditional(spec, "zero-init:" + idx.toString()) and
lhs = spec.getNameExpr(idx)
)
} or
/** A composite literal element target. */
MkLiteralElementTarget(ControlFlow::Node write) {

View File

@@ -1227,17 +1227,15 @@
| exprs.go:40:2:40:12 | declaration statement | exprs.go:40:2:40:12 | variable declaration |
| exprs.go:40:2:40:12 | variable declaration | exprs.go:40:6:40:12 | value declaration specifier |
| exprs.go:40:6:40:12 | After value declaration specifier | exprs.go:40:2:40:12 | After variable declaration |
| exprs.go:40:6:40:12 | assign:0 value declaration specifier | exprs.go:40:6:40:12 | After value declaration specifier |
| exprs.go:40:6:40:12 | value declaration specifier | exprs.go:40:6:40:12 | zero-init:0 value declaration specifier |
| exprs.go:40:6:40:12 | zero-init:0 value declaration specifier | exprs.go:40:6:40:12 | assign:0 value declaration specifier |
| exprs.go:40:6:40:12 | zero-init:0 value declaration specifier | exprs.go:40:6:40:12 | After value declaration specifier |
| exprs.go:41:2:41:12 | After declaration statement | exprs.go:42:2:42:20 | ... = ... |
| exprs.go:41:2:41:12 | After variable declaration | exprs.go:41:2:41:12 | After declaration statement |
| exprs.go:41:2:41:12 | declaration statement | exprs.go:41:2:41:12 | variable declaration |
| exprs.go:41:2:41:12 | variable declaration | exprs.go:41:6:41:12 | value declaration specifier |
| exprs.go:41:6:41:12 | After value declaration specifier | exprs.go:41:2:41:12 | After variable declaration |
| exprs.go:41:6:41:12 | assign:0 value declaration specifier | exprs.go:41:6:41:12 | After value declaration specifier |
| exprs.go:41:6:41:12 | value declaration specifier | exprs.go:41:6:41:12 | zero-init:0 value declaration specifier |
| exprs.go:41:6:41:12 | zero-init:0 value declaration specifier | exprs.go:41:6:41:12 | assign:0 value declaration specifier |
| exprs.go:41:6:41:12 | zero-init:0 value declaration specifier | exprs.go:41:6:41:12 | After value declaration specifier |
| exprs.go:42:2:42:20 | ... = ... | exprs.go:42:10:42:20 | Before type assertion |
| exprs.go:42:2:42:20 | After ... = ... | exprs.go:43:2:45:2 | if statement |
| exprs.go:42:2:42:20 | assign:0 ... = ... | exprs.go:42:2:42:20 | extract:1 ... = ... |
@@ -1899,9 +1897,8 @@
| main.go:13:2:13:10 | declaration statement | main.go:13:2:13:10 | variable declaration |
| main.go:13:2:13:10 | variable declaration | main.go:13:6:13:10 | value declaration specifier |
| main.go:13:6:13:10 | After value declaration specifier | main.go:13:2:13:10 | After variable declaration |
| main.go:13:6:13:10 | assign:0 value declaration specifier | main.go:13:6:13:10 | After value declaration specifier |
| main.go:13:6:13:10 | value declaration specifier | main.go:13:6:13:10 | zero-init:0 value declaration specifier |
| main.go:13:6:13:10 | zero-init:0 value declaration specifier | main.go:13:6:13:10 | assign:0 value declaration specifier |
| main.go:13:6:13:10 | zero-init:0 value declaration specifier | main.go:13:6:13:10 | After value declaration specifier |
| main.go:14:2:14:8 | ... := ... | main.go:14:7:14:8 | Before 23 |
| main.go:14:2:14:8 | After ... := ... | main.go:15:2:15:16 | expression statement |
| main.go:14:2:14:8 | assign:0 ... := ... | main.go:14:2:14:8 | After ... := ... |
@@ -2207,9 +2204,8 @@
| main.go:67:2:67:10 | declaration statement | main.go:67:2:67:10 | variable declaration |
| main.go:67:2:67:10 | variable declaration | main.go:67:6:67:10 | value declaration specifier |
| main.go:67:6:67:10 | After value declaration specifier | main.go:67:2:67:10 | After variable declaration |
| main.go:67:6:67:10 | assign:0 value declaration specifier | main.go:67:6:67:10 | After value declaration specifier |
| main.go:67:6:67:10 | value declaration specifier | main.go:67:6:67:10 | zero-init:0 value declaration specifier |
| main.go:67:6:67:10 | zero-init:0 value declaration specifier | main.go:67:6:67:10 | assign:0 value declaration specifier |
| main.go:67:6:67:10 | zero-init:0 value declaration specifier | main.go:67:6:67:10 | After value declaration specifier |
| main.go:68:2:70:2 | After for statement | main.go:71:2:71:13 | expression statement |
| main.go:68:2:70:2 | [LoopHeader] for statement | main.go:68:6:68:11 | Before call to cond |
| main.go:68:2:70:2 | for statement | main.go:68:6:68:11 | Before call to cond |
@@ -2785,13 +2781,11 @@
| stmts3.go:7:9:7:12 | Before iota | stmts3.go:7:9:7:12 | iota |
| stmts3.go:7:9:7:12 | iota | stmts3.go:7:9:7:12 | After iota |
| stmts3.go:8:3:8:7 | After value declaration specifier | stmts3.go:9:3:9:6 | value declaration specifier |
| stmts3.go:8:3:8:7 | assign:0 value declaration specifier | stmts3.go:8:3:8:7 | After value declaration specifier |
| stmts3.go:8:3:8:7 | value declaration specifier | stmts3.go:8:3:8:7 | zero-init:0 value declaration specifier |
| stmts3.go:8:3:8:7 | zero-init:0 value declaration specifier | stmts3.go:8:3:8:7 | assign:0 value declaration specifier |
| stmts3.go:8:3:8:7 | zero-init:0 value declaration specifier | stmts3.go:8:3:8:7 | After value declaration specifier |
| stmts3.go:9:3:9:6 | After value declaration specifier | stmts3.go:6:2:10:2 | After constant declaration |
| stmts3.go:9:3:9:6 | assign:0 value declaration specifier | stmts3.go:9:3:9:6 | After value declaration specifier |
| stmts3.go:9:3:9:6 | value declaration specifier | stmts3.go:9:3:9:6 | zero-init:0 value declaration specifier |
| stmts3.go:9:3:9:6 | zero-init:0 value declaration specifier | stmts3.go:9:3:9:6 | assign:0 value declaration specifier |
| stmts3.go:9:3:9:6 | zero-init:0 value declaration specifier | stmts3.go:9:3:9:6 | After value declaration specifier |
| stmts3.go:11:2:11:26 | Before return statement | stmts3.go:11:9:11:26 | Before ...-... |
| stmts3.go:11:2:11:26 | return statement | stmts3.go:5:1:12:1 | Normal Exit |
| stmts3.go:11:9:11:11 | After red | stmts3.go:11:15:11:19 | Before green |
@@ -3307,17 +3301,15 @@
| stmts.go:47:2:47:17 | declaration statement | stmts.go:47:2:47:17 | variable declaration |
| stmts.go:47:2:47:17 | variable declaration | stmts.go:47:6:47:17 | value declaration specifier |
| stmts.go:47:6:47:17 | After value declaration specifier | stmts.go:47:2:47:17 | After variable declaration |
| stmts.go:47:6:47:17 | assign:0 value declaration specifier | stmts.go:47:6:47:17 | After value declaration specifier |
| stmts.go:47:6:47:17 | value declaration specifier | stmts.go:47:6:47:17 | zero-init:0 value declaration specifier |
| stmts.go:47:6:47:17 | zero-init:0 value declaration specifier | stmts.go:47:6:47:17 | assign:0 value declaration specifier |
| stmts.go:47:6:47:17 | zero-init:0 value declaration specifier | stmts.go:47:6:47:17 | After value declaration specifier |
| stmts.go:48:2:48:11 | After declaration statement | stmts.go:50:2:59:2 | Before select statement |
| stmts.go:48:2:48:11 | After variable declaration | stmts.go:48:2:48:11 | After declaration statement |
| stmts.go:48:2:48:11 | declaration statement | stmts.go:48:2:48:11 | variable declaration |
| stmts.go:48:2:48:11 | variable declaration | stmts.go:48:6:48:11 | value declaration specifier |
| stmts.go:48:6:48:11 | After value declaration specifier | stmts.go:48:2:48:11 | After variable declaration |
| stmts.go:48:6:48:11 | assign:0 value declaration specifier | stmts.go:48:6:48:11 | After value declaration specifier |
| stmts.go:48:6:48:11 | value declaration specifier | stmts.go:48:6:48:11 | zero-init:0 value declaration specifier |
| stmts.go:48:6:48:11 | zero-init:0 value declaration specifier | stmts.go:48:6:48:11 | assign:0 value declaration specifier |
| stmts.go:48:6:48:11 | zero-init:0 value declaration specifier | stmts.go:48:6:48:11 | After value declaration specifier |
| stmts.go:50:2:59:2 | After select statement | stmts.go:61:2:61:10 | Before select statement |
| stmts.go:50:2:59:2 | Before select statement | stmts.go:51:9:51:11 | Before ch1 |
| stmts.go:50:2:59:2 | select statement | stmts.go:51:2:52:31 | comm clause |

View File

@@ -1,4 +1,4 @@
| main.go:13:6:13:10 | assign:0 value declaration specifier | main.go:13:6:13:6 | x | main.go:13:6:13:10 | zero-init:0 value declaration specifier |
| main.go:13:6:13:10 | zero-init:0 value declaration specifier | main.go:13:6:13:6 | x | main.go:13:6:13:10 | zero-init:0 value declaration specifier |
| main.go:14:2:14:8 | assign:0 ... := ... | main.go:14:2:14:2 | y | main.go:14:7:14:8 | 23 |
| main.go:17:3:17:9 | compound-rhs ... += ... | main.go:14:2:14:2 | y | main.go:17:3:17:9 | compound-rhs ... += ... |
| main.go:21:3:21:7 | assign:0 ... = ... | main.go:13:6:13:6 | x | main.go:21:7:21:7 | y |
@@ -13,7 +13,7 @@
| main.go:47:25:50:1 | result-zero-init:0 block statement | main.go:47:13:47:18 | result | main.go:47:25:50:1 | result-zero-init:0 block statement |
| main.go:48:2:48:12 | assign:0 ... = ... | main.go:47:13:47:18 | result | main.go:48:11:48:12 | 42 |
| main.go:52:26:54:1 | result-zero-init:0 block statement | main.go:52:14:52:19 | result | main.go:52:26:54:1 | result-zero-init:0 block statement |
| main.go:57:6:57:10 | assign:0 value declaration specifier | main.go:57:6:57:6 | x | main.go:57:6:57:10 | zero-init:0 value declaration specifier |
| main.go:57:6:57:10 | zero-init:0 value declaration specifier | main.go:57:6:57:6 | x | main.go:57:6:57:10 | zero-init:0 value declaration specifier |
| 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 |
@@ -39,7 +39,7 @@
| main.go:113:2:113:7 | assign:0 ... := ... | main.go:113:2:113:2 | x | main.go:113:7:113:7 | 0 |
| main.go:115:3:115:12 | assign:0 ... := ... | main.go:115:3:115:3 | y | main.go:115:8:115:12 | ...+... |
| main.go:116:3:116:7 | assign:0 ... = ... | main.go:113:2:113:2 | x | main.go:116:7:116:7 | y |
| main.go:128:6:128:8 | assign:0 value declaration specifier | main.go:128:6:128:6 | p | main.go:128:6:128:8 | zero-init:0 value declaration specifier |
| main.go:128:6:128:8 | zero-init:0 value declaration specifier | main.go:128:6:128:6 | p | main.go:128:6:128:8 | zero-init:0 value declaration specifier |
| main.go:130:3:130:24 | assign:0 ... = ... | main.go:128:6:128:6 | p | main.go:130:7:130:24 | struct literal |
| main.go:130:9:130:9 | lit-init 2 | main.go:122:2:122:2 | a | main.go:130:9:130:9 | 2 |
| main.go:130:12:130:18 | lit-init struct literal | main.go:123:2:123:2 | b | main.go:130:12:130:18 | struct literal |