Skip to content

Commit d30162b

Browse files
committed
Fold uninitialised var-decl zero-init and write into one node
1 parent 1c60ffa commit d30162b

4 files changed

Lines changed: 52 additions & 25 deletions

File tree

go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,11 @@ module GoCfg {
508508
// so the guard itself emits no assignment write node.
509509
not n = any(Go::TypeSwitchStmt ts).getAssign()
510510
or
511-
notBlankIdent(n.(Go::ValueSpec).getNameExpr(i))
511+
// A `ValueSpec` without an initializer is written by its `zero-init`
512+
// node directly (see `IR::InitVariableInstruction`), so only specs
513+
// *with* an initializer emit an `assign` write node.
514+
notBlankIdent(n.(Go::ValueSpec).getNameExpr(i)) and
515+
exists(n.(Go::ValueSpec).getAnInit())
512516
or
513517
notBlankIdent(n.(Go::RangeElementExpr).getKey()) and i = 0
514518
or
@@ -1103,7 +1107,10 @@ module GoCfg {
11031107
// above, so they emit no separate `assign:j` node.
11041108
not assgn instanceof Go::CompoundAssignStmt
11051109
or
1106-
notBlankIdent(assgn.(Go::ValueSpec).getNameExpr(j))
1110+
// A `ValueSpec` without an initializer is written by its `zero-init`
1111+
// node directly, so only specs *with* an initializer emit `assign:j`.
1112+
notBlankIdent(assgn.(Go::ValueSpec).getNameExpr(j)) and
1113+
exists(assgn.(Go::ValueSpec).getAnInit())
11071114
or
11081115
notBlankIdent(assgn.(Go::RangeElementExpr).getKey()) and j = 0
11091116
or

go/ql/lib/semmle/go/controlflow/IR.qll

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,11 @@ module IR {
641641
(
642642
exists(assgn.(Assignment).getLhs(i))
643643
or
644-
exists(assgn.(ValueSpec).getNameExpr(i))
644+
// A `ValueSpec` without an initializer (`var x int`) is written by its
645+
// `zero-init` node directly (see `InitVariableInstruction`), so only
646+
// specs *with* an initializer produce an `assign` node.
647+
exists(assgn.(ValueSpec).getNameExpr(i)) and
648+
exists(assgn.(ValueSpec).getAnInit())
645649
or
646650
assgn instanceof RangeElementExpr and i in [0, 1]
647651
)
@@ -656,9 +660,6 @@ module IR {
656660
exists(ValueSpec spec | spec = assgn |
657661
spec.getNumName() = spec.getNumInit() and
658662
result = evalExprInstruction(spec.getInit(i))
659-
or
660-
result =
661-
implicitInitInstruction(any(ValueEntity v | spec.getNameExpr(i) = v.getDeclaration()))
662663
)
663664
or
664665
result.(ExtractTupleElementInstruction).isAdditional(assgn, "extract:" + i.toString())
@@ -1005,6 +1006,28 @@ module IR {
10051006
override ControlFlow::Root getRoot() { result = res.getFunction() }
10061007
}
10071008

1009+
/**
1010+
* An instruction initializing a variable declared without an initializer
1011+
* (`var x int`) to its zero value.
1012+
*
1013+
* This is the same node as the `EvalImplicitInitInstruction` that computes the
1014+
* zero value: the zero-value instruction performs the write of the variable
1015+
* directly, rather than feeding a separate write node.
1016+
*/
1017+
class InitVariableInstruction extends WriteInstruction {
1018+
ValueSpec spec;
1019+
int idx;
1020+
1021+
InitVariableInstruction() {
1022+
this.isAdditional(spec, "zero-init:" + idx.toString()) and
1023+
exists(spec.getNameExpr(idx))
1024+
}
1025+
1026+
override Instruction getRhs() { result = this }
1027+
1028+
override ControlFlow::Root getRoot() { result.isRootOf(spec) }
1029+
}
1030+
10081031
/** An instruction that gets the next key-value pair in a range loop. */
10091032
class GetNextEntryInstruction extends Instruction {
10101033
RangeElementExpr p;
@@ -1123,6 +1146,11 @@ module IR {
11231146
write.isAdditional(fd.getBody(), "result-zero-init:" + idx.toString()) and
11241147
lhs = fd.getResultVar(idx).getDeclaration()
11251148
)
1149+
or
1150+
exists(ValueSpec spec, int idx |
1151+
write.isAdditional(spec, "zero-init:" + idx.toString()) and
1152+
lhs = spec.getNameExpr(idx)
1153+
)
11261154
} or
11271155
/** A composite literal element target. */
11281156
MkLiteralElementTarget(ControlFlow::Node write) {

go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/ControlFlowNode_getASuccessor.expected

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,17 +1227,15 @@
12271227
| exprs.go:40:2:40:12 | declaration statement | exprs.go:40:2:40:12 | variable declaration |
12281228
| exprs.go:40:2:40:12 | variable declaration | exprs.go:40:6:40:12 | value declaration specifier |
12291229
| exprs.go:40:6:40:12 | After value declaration specifier | exprs.go:40:2:40:12 | After variable declaration |
1230-
| exprs.go:40:6:40:12 | assign:0 value declaration specifier | exprs.go:40:6:40:12 | After value declaration specifier |
12311230
| exprs.go:40:6:40:12 | value declaration specifier | exprs.go:40:6:40:12 | zero-init:0 value declaration specifier |
1232-
| exprs.go:40:6:40:12 | zero-init:0 value declaration specifier | exprs.go:40:6:40:12 | assign:0 value declaration specifier |
1231+
| exprs.go:40:6:40:12 | zero-init:0 value declaration specifier | exprs.go:40:6:40:12 | After value declaration specifier |
12331232
| exprs.go:41:2:41:12 | After declaration statement | exprs.go:42:2:42:20 | ... = ... |
12341233
| exprs.go:41:2:41:12 | After variable declaration | exprs.go:41:2:41:12 | After declaration statement |
12351234
| exprs.go:41:2:41:12 | declaration statement | exprs.go:41:2:41:12 | variable declaration |
12361235
| exprs.go:41:2:41:12 | variable declaration | exprs.go:41:6:41:12 | value declaration specifier |
12371236
| exprs.go:41:6:41:12 | After value declaration specifier | exprs.go:41:2:41:12 | After variable declaration |
1238-
| exprs.go:41:6:41:12 | assign:0 value declaration specifier | exprs.go:41:6:41:12 | After value declaration specifier |
12391237
| exprs.go:41:6:41:12 | value declaration specifier | exprs.go:41:6:41:12 | zero-init:0 value declaration specifier |
1240-
| exprs.go:41:6:41:12 | zero-init:0 value declaration specifier | exprs.go:41:6:41:12 | assign:0 value declaration specifier |
1238+
| exprs.go:41:6:41:12 | zero-init:0 value declaration specifier | exprs.go:41:6:41:12 | After value declaration specifier |
12411239
| exprs.go:42:2:42:20 | ... = ... | exprs.go:42:10:42:20 | Before type assertion |
12421240
| exprs.go:42:2:42:20 | After ... = ... | exprs.go:43:2:45:2 | if statement |
12431241
| exprs.go:42:2:42:20 | assign:0 ... = ... | exprs.go:42:2:42:20 | extract:1 ... = ... |
@@ -1899,9 +1897,8 @@
18991897
| main.go:13:2:13:10 | declaration statement | main.go:13:2:13:10 | variable declaration |
19001898
| main.go:13:2:13:10 | variable declaration | main.go:13:6:13:10 | value declaration specifier |
19011899
| main.go:13:6:13:10 | After value declaration specifier | main.go:13:2:13:10 | After variable declaration |
1902-
| main.go:13:6:13:10 | assign:0 value declaration specifier | main.go:13:6:13:10 | After value declaration specifier |
19031900
| main.go:13:6:13:10 | value declaration specifier | main.go:13:6:13:10 | zero-init:0 value declaration specifier |
1904-
| main.go:13:6:13:10 | zero-init:0 value declaration specifier | main.go:13:6:13:10 | assign:0 value declaration specifier |
1901+
| main.go:13:6:13:10 | zero-init:0 value declaration specifier | main.go:13:6:13:10 | After value declaration specifier |
19051902
| main.go:14:2:14:8 | ... := ... | main.go:14:7:14:8 | Before 23 |
19061903
| main.go:14:2:14:8 | After ... := ... | main.go:15:2:15:16 | expression statement |
19071904
| main.go:14:2:14:8 | assign:0 ... := ... | main.go:14:2:14:8 | After ... := ... |
@@ -2207,9 +2204,8 @@
22072204
| main.go:67:2:67:10 | declaration statement | main.go:67:2:67:10 | variable declaration |
22082205
| main.go:67:2:67:10 | variable declaration | main.go:67:6:67:10 | value declaration specifier |
22092206
| main.go:67:6:67:10 | After value declaration specifier | main.go:67:2:67:10 | After variable declaration |
2210-
| main.go:67:6:67:10 | assign:0 value declaration specifier | main.go:67:6:67:10 | After value declaration specifier |
22112207
| main.go:67:6:67:10 | value declaration specifier | main.go:67:6:67:10 | zero-init:0 value declaration specifier |
2212-
| main.go:67:6:67:10 | zero-init:0 value declaration specifier | main.go:67:6:67:10 | assign:0 value declaration specifier |
2208+
| main.go:67:6:67:10 | zero-init:0 value declaration specifier | main.go:67:6:67:10 | After value declaration specifier |
22132209
| main.go:68:2:70:2 | After for statement | main.go:71:2:71:13 | expression statement |
22142210
| main.go:68:2:70:2 | [LoopHeader] for statement | main.go:68:6:68:11 | Before call to cond |
22152211
| main.go:68:2:70:2 | for statement | main.go:68:6:68:11 | Before call to cond |
@@ -2785,13 +2781,11 @@
27852781
| stmts3.go:7:9:7:12 | Before iota | stmts3.go:7:9:7:12 | iota |
27862782
| stmts3.go:7:9:7:12 | iota | stmts3.go:7:9:7:12 | After iota |
27872783
| stmts3.go:8:3:8:7 | After value declaration specifier | stmts3.go:9:3:9:6 | value declaration specifier |
2788-
| stmts3.go:8:3:8:7 | assign:0 value declaration specifier | stmts3.go:8:3:8:7 | After value declaration specifier |
27892784
| stmts3.go:8:3:8:7 | value declaration specifier | stmts3.go:8:3:8:7 | zero-init:0 value declaration specifier |
2790-
| stmts3.go:8:3:8:7 | zero-init:0 value declaration specifier | stmts3.go:8:3:8:7 | assign:0 value declaration specifier |
2785+
| stmts3.go:8:3:8:7 | zero-init:0 value declaration specifier | stmts3.go:8:3:8:7 | After value declaration specifier |
27912786
| stmts3.go:9:3:9:6 | After value declaration specifier | stmts3.go:6:2:10:2 | After constant declaration |
2792-
| stmts3.go:9:3:9:6 | assign:0 value declaration specifier | stmts3.go:9:3:9:6 | After value declaration specifier |
27932787
| stmts3.go:9:3:9:6 | value declaration specifier | stmts3.go:9:3:9:6 | zero-init:0 value declaration specifier |
2794-
| stmts3.go:9:3:9:6 | zero-init:0 value declaration specifier | stmts3.go:9:3:9:6 | assign:0 value declaration specifier |
2788+
| stmts3.go:9:3:9:6 | zero-init:0 value declaration specifier | stmts3.go:9:3:9:6 | After value declaration specifier |
27952789
| stmts3.go:11:2:11:26 | Before return statement | stmts3.go:11:9:11:26 | Before ...-... |
27962790
| stmts3.go:11:2:11:26 | return statement | stmts3.go:5:1:12:1 | Normal Exit |
27972791
| stmts3.go:11:9:11:11 | After red | stmts3.go:11:15:11:19 | Before green |
@@ -3307,17 +3301,15 @@
33073301
| stmts.go:47:2:47:17 | declaration statement | stmts.go:47:2:47:17 | variable declaration |
33083302
| stmts.go:47:2:47:17 | variable declaration | stmts.go:47:6:47:17 | value declaration specifier |
33093303
| stmts.go:47:6:47:17 | After value declaration specifier | stmts.go:47:2:47:17 | After variable declaration |
3310-
| stmts.go:47:6:47:17 | assign:0 value declaration specifier | stmts.go:47:6:47:17 | After value declaration specifier |
33113304
| stmts.go:47:6:47:17 | value declaration specifier | stmts.go:47:6:47:17 | zero-init:0 value declaration specifier |
3312-
| stmts.go:47:6:47:17 | zero-init:0 value declaration specifier | stmts.go:47:6:47:17 | assign:0 value declaration specifier |
3305+
| stmts.go:47:6:47:17 | zero-init:0 value declaration specifier | stmts.go:47:6:47:17 | After value declaration specifier |
33133306
| stmts.go:48:2:48:11 | After declaration statement | stmts.go:50:2:59:2 | Before select statement |
33143307
| stmts.go:48:2:48:11 | After variable declaration | stmts.go:48:2:48:11 | After declaration statement |
33153308
| stmts.go:48:2:48:11 | declaration statement | stmts.go:48:2:48:11 | variable declaration |
33163309
| stmts.go:48:2:48:11 | variable declaration | stmts.go:48:6:48:11 | value declaration specifier |
33173310
| stmts.go:48:6:48:11 | After value declaration specifier | stmts.go:48:2:48:11 | After variable declaration |
3318-
| stmts.go:48:6:48:11 | assign:0 value declaration specifier | stmts.go:48:6:48:11 | After value declaration specifier |
33193311
| stmts.go:48:6:48:11 | value declaration specifier | stmts.go:48:6:48:11 | zero-init:0 value declaration specifier |
3320-
| stmts.go:48:6:48:11 | zero-init:0 value declaration specifier | stmts.go:48:6:48:11 | assign:0 value declaration specifier |
3312+
| stmts.go:48:6:48:11 | zero-init:0 value declaration specifier | stmts.go:48:6:48:11 | After value declaration specifier |
33213313
| stmts.go:50:2:59:2 | After select statement | stmts.go:61:2:61:10 | Before select statement |
33223314
| stmts.go:50:2:59:2 | Before select statement | stmts.go:51:9:51:11 | Before ch1 |
33233315
| stmts.go:50:2:59:2 | select statement | stmts.go:51:2:52:31 | comm clause |

go/ql/test/library-tests/semmle/go/dataflow/SSA/VarDefs.expected

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
| 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 |
1+
| 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 |
22
| main.go:14:2:14:8 | assign:0 ... := ... | main.go:14:2:14:2 | y | main.go:14:7:14:8 | 23 |
33
| main.go:17:3:17:9 | compound-rhs ... += ... | main.go:14:2:14:2 | y | main.go:17:3:17:9 | compound-rhs ... += ... |
44
| 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 @@
1313
| 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 |
1414
| main.go:48:2:48:12 | assign:0 ... = ... | main.go:47:13:47:18 | result | main.go:48:11:48:12 | 42 |
1515
| 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 |
16-
| 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 |
16+
| 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 |
1717
| main.go:59:3:59:7 | assign:0 ... = ... | main.go:57:6:57:6 | x | main.go:59:7:59:7 | 2 |
1818
| main.go:63:2:63:7 | assign:0 ... := ... | main.go:63:2:63:2 | y | main.go:63:7:63:7 | 1 |
1919
| 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 @@
3939
| main.go:113:2:113:7 | assign:0 ... := ... | main.go:113:2:113:2 | x | main.go:113:7:113:7 | 0 |
4040
| main.go:115:3:115:12 | assign:0 ... := ... | main.go:115:3:115:3 | y | main.go:115:8:115:12 | ...+... |
4141
| main.go:116:3:116:7 | assign:0 ... = ... | main.go:113:2:113:2 | x | main.go:116:7:116:7 | y |
42-
| 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 |
42+
| 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 |
4343
| main.go:130:3:130:24 | assign:0 ... = ... | main.go:128:6:128:6 | p | main.go:130:7:130:24 | struct literal |
4444
| main.go:130:9:130:9 | lit-init 2 | main.go:122:2:122:2 | a | main.go:130:9:130:9 | 2 |
4545
| 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 |

0 commit comments

Comments
 (0)