Skip to content

Commit dfd73a1

Browse files
committed
Go CFG: fold implicit literal element index into the lit-init node
A positional element of an array or slice literal (e.g. the elements of []T{a, b}) previously created a 'lit-index' node holding its implicit index constant (0, 1, ...), in addition to the 'lit-init' write node. Array and slice content flow is index-insensitive (the store step ignores the element index), map literals always use explicit keys, and literal bases are not tracked by VariableWithFields, so the implicit index value is never actually consumed. Drop the 'lit-index' node and let the lit-init instruction act as its own opaque index. All 100 data-flow library tests pass unchanged, confirming no content-flow loss.
1 parent 779edbf commit dfd73a1

3 files changed

Lines changed: 16 additions & 82 deletions

File tree

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

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -587,14 +587,6 @@ module GoCfg {
587587
n = any(Go::CompositeLit lit).getAnElement() and
588588
tag = "lit-init"
589589
or
590-
// Implicit literal element index
591-
exists(Go::CompositeLit lit |
592-
not lit instanceof Go::StructLit and
593-
n = lit.getAnElement() and
594-
not n instanceof Go::KeyValueExpr and
595-
tag = "lit-index"
596-
)
597-
or
598590
// Implicit field selection for promoted fields
599591
exists(int i, Go::Field implicitField |
600592
implicitFieldSelection(n, i, implicitField) and
@@ -1480,17 +1472,12 @@ module GoCfg {
14801472
not exists(lit.getElement(_)) and n2.isAfter(lit)
14811473
)
14821474
or
1483-
// After element → optional lit-index → lit-init → next element or After
1475+
// After element → lit-init → next element or After.
1476+
// Positional array/slice elements have an implicit index that is
1477+
// modelled on the `lit-init` instruction itself (see
1478+
// `IR::InitLiteralElementInstruction`) rather than as a separate node.
14841479
exists(int i |
14851480
n1.isAfter(lit.getElement(i)) and
1486-
(
1487-
n2.isAdditional(lit.getElement(i), "lit-index")
1488-
or
1489-
not exists(PreControlFlowNode idx | idx.isAdditional(lit.getElement(i), "lit-index")) and
1490-
n2.isAdditional(lit.getElement(i), "lit-init")
1491-
)
1492-
or
1493-
n1.isAdditional(lit.getElement(i), "lit-index") and
14941481
n2.isAdditional(lit.getElement(i), "lit-init")
14951482
or
14961483
n1.isAdditional(lit.getElement(i), "lit-init") and

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

Lines changed: 5 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,6 @@ module IR {
167167
or
168168
this instanceof InitLiteralComponentInstruction and result = "element init"
169169
or
170-
this instanceof ImplicitLiteralElementIndexInstruction and result = "element index"
171-
or
172170
this instanceof AssignInstruction and result = "assignment"
173171
or
174172
this instanceof EvalCompoundAssignRhsInstruction and
@@ -585,7 +583,11 @@ module IR {
585583
Instruction getIndex() {
586584
result = evalExprInstruction(elt.(KeyValueExpr).getKey())
587585
or
588-
result.(ImplicitLiteralElementIndexInstruction).isAdditional(elt, "lit-index")
586+
// A positional array/slice element has an implicit index. Array/slice
587+
// content flow is index-insensitive, so rather than materialise a
588+
// separate index node the element-init instruction acts as its own
589+
// (opaque) index.
590+
not elt instanceof KeyValueExpr and result = this
589591
}
590592
}
591593

@@ -634,54 +636,6 @@ module IR {
634636
}
635637
}
636638

637-
private predicate noExplicitKeys(CompositeLit lit) {
638-
not lit.getAnElement() instanceof KeyValueExpr
639-
}
640-
641-
private int getElementIndex(CompositeLit lit, int i) {
642-
(
643-
lit.getType().getUnderlyingType() instanceof ArrayType or
644-
lit.getType().getUnderlyingType() instanceof SliceType
645-
) and
646-
exists(Expr elt | elt = lit.getElement(i) |
647-
noExplicitKeys(lit) and result = i
648-
or
649-
result = elt.(KeyValueExpr).getKey().getIntValue()
650-
or
651-
not elt instanceof KeyValueExpr and
652-
(
653-
i = 0 and result = 0
654-
or
655-
result = getElementIndex(lit, i - 1) + 1
656-
)
657-
)
658-
}
659-
660-
/**
661-
* An IR instruction computing the implicit index of an element in an array or slice literal.
662-
*/
663-
class ImplicitLiteralElementIndexInstruction extends Instruction {
664-
Expr elt;
665-
666-
ImplicitLiteralElementIndexInstruction() { this.isAdditional(elt, "lit-index") }
667-
668-
override Type getResultType() { result instanceof IntType }
669-
670-
override ControlFlow::Root getRoot() { result.isRootOf(elt) }
671-
672-
override int getIntValue() {
673-
exists(CompositeLit lit, int i | elt = lit.getElement(i) | result = getElementIndex(lit, i))
674-
}
675-
676-
override string getStringValue() { none() }
677-
678-
override string getExactValue() { result = this.getIntValue().toString() }
679-
680-
override predicate isPlatformIndependentConstant() { any() }
681-
682-
override predicate isConst() { any() }
683-
}
684-
685639
/**
686640
* An instruction assigning to a variable or field.
687641
*/

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

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -969,9 +969,8 @@
969969
| exprs.go:16:17:16:23 | After struct3 | exprs.go:16:17:16:25 | selection of x |
970970
| exprs.go:16:17:16:23 | Before struct3 | exprs.go:16:17:16:23 | struct3 |
971971
| exprs.go:16:17:16:23 | struct3 | exprs.go:16:17:16:23 | After struct3 |
972-
| exprs.go:16:17:16:25 | After selection of x | exprs.go:16:17:16:25 | lit-index selection of x |
972+
| exprs.go:16:17:16:25 | After selection of x | exprs.go:16:17:16:25 | lit-init selection of x |
973973
| exprs.go:16:17:16:25 | Before selection of x | exprs.go:16:17:16:23 | Before struct3 |
974-
| exprs.go:16:17:16:25 | lit-index selection of x | exprs.go:16:17:16:25 | lit-init selection of x |
975974
| exprs.go:16:17:16:25 | lit-init selection of x | exprs.go:16:10:16:26 | After array literal |
976975
| exprs.go:16:17:16:25 | selection of x | exprs.go:16:17:16:25 | After selection of x |
977976
| exprs.go:17:2:17:40 | ... := ... | exprs.go:17:10:17:40 | Before array literal |
@@ -983,9 +982,8 @@
983982
| exprs.go:17:19:17:25 | After struct3 | exprs.go:17:19:17:27 | selection of x |
984983
| exprs.go:17:19:17:25 | Before struct3 | exprs.go:17:19:17:25 | struct3 |
985984
| exprs.go:17:19:17:25 | struct3 | exprs.go:17:19:17:25 | After struct3 |
986-
| exprs.go:17:19:17:27 | After selection of x | exprs.go:17:19:17:27 | lit-index selection of x |
985+
| exprs.go:17:19:17:27 | After selection of x | exprs.go:17:19:17:27 | lit-init selection of x |
987986
| exprs.go:17:19:17:27 | Before selection of x | exprs.go:17:19:17:25 | Before struct3 |
988-
| exprs.go:17:19:17:27 | lit-index selection of x | exprs.go:17:19:17:27 | lit-init selection of x |
989987
| exprs.go:17:19:17:27 | lit-init selection of x | exprs.go:17:30:17:39 | Before key-value pair |
990988
| exprs.go:17:19:17:27 | selection of x | exprs.go:17:19:17:27 | After selection of x |
991989
| exprs.go:17:30:17:30 | 2 | exprs.go:17:30:17:30 | After 2 |
@@ -1011,14 +1009,12 @@
10111009
| exprs.go:18:9:18:22 | After slice literal | exprs.go:18:2:18:22 | assign:0 ... := ... |
10121010
| exprs.go:18:9:18:22 | Before slice literal | exprs.go:18:9:18:22 | slice literal |
10131011
| exprs.go:18:9:18:22 | slice literal | exprs.go:18:18:18:18 | Before s |
1014-
| exprs.go:18:18:18:18 | After s | exprs.go:18:18:18:18 | lit-index s |
1012+
| exprs.go:18:18:18:18 | After s | exprs.go:18:18:18:18 | lit-init s |
10151013
| exprs.go:18:18:18:18 | Before s | exprs.go:18:18:18:18 | s |
1016-
| exprs.go:18:18:18:18 | lit-index s | exprs.go:18:18:18:18 | lit-init s |
10171014
| exprs.go:18:18:18:18 | lit-init s | exprs.go:18:21:18:21 | Before s |
10181015
| exprs.go:18:18:18:18 | s | exprs.go:18:18:18:18 | After s |
1019-
| exprs.go:18:21:18:21 | After s | exprs.go:18:21:18:21 | lit-index s |
1016+
| exprs.go:18:21:18:21 | After s | exprs.go:18:21:18:21 | lit-init s |
10201017
| exprs.go:18:21:18:21 | Before s | exprs.go:18:21:18:21 | s |
1021-
| exprs.go:18:21:18:21 | lit-index s | exprs.go:18:21:18:21 | lit-init s |
10221018
| exprs.go:18:21:18:21 | lit-init s | exprs.go:18:9:18:22 | After slice literal |
10231019
| exprs.go:18:21:18:21 | s | exprs.go:18:21:18:21 | After s |
10241020
| exprs.go:19:2:19:38 | ... := ... | exprs.go:19:8:19:38 | Before map literal |
@@ -1373,19 +1369,16 @@
13731369
| exprs.go:61:9:61:22 | Before slice literal | exprs.go:61:9:61:22 | slice literal |
13741370
| exprs.go:61:9:61:22 | slice literal | exprs.go:61:15:61:15 | Before 1 |
13751371
| exprs.go:61:15:61:15 | 1 | exprs.go:61:15:61:15 | After 1 |
1376-
| exprs.go:61:15:61:15 | After 1 | exprs.go:61:15:61:15 | lit-index 1 |
1372+
| exprs.go:61:15:61:15 | After 1 | exprs.go:61:15:61:15 | lit-init 1 |
13771373
| exprs.go:61:15:61:15 | Before 1 | exprs.go:61:15:61:15 | 1 |
1378-
| exprs.go:61:15:61:15 | lit-index 1 | exprs.go:61:15:61:15 | lit-init 1 |
13791374
| exprs.go:61:15:61:15 | lit-init 1 | exprs.go:61:18:61:18 | Before 2 |
13801375
| exprs.go:61:18:61:18 | 2 | exprs.go:61:18:61:18 | After 2 |
1381-
| exprs.go:61:18:61:18 | After 2 | exprs.go:61:18:61:18 | lit-index 2 |
1376+
| exprs.go:61:18:61:18 | After 2 | exprs.go:61:18:61:18 | lit-init 2 |
13821377
| exprs.go:61:18:61:18 | Before 2 | exprs.go:61:18:61:18 | 2 |
1383-
| exprs.go:61:18:61:18 | lit-index 2 | exprs.go:61:18:61:18 | lit-init 2 |
13841378
| exprs.go:61:18:61:18 | lit-init 2 | exprs.go:61:21:61:21 | Before 3 |
13851379
| exprs.go:61:21:61:21 | 3 | exprs.go:61:21:61:21 | After 3 |
1386-
| exprs.go:61:21:61:21 | After 3 | exprs.go:61:21:61:21 | lit-index 3 |
1380+
| exprs.go:61:21:61:21 | After 3 | exprs.go:61:21:61:21 | lit-init 3 |
13871381
| exprs.go:61:21:61:21 | Before 3 | exprs.go:61:21:61:21 | 3 |
1388-
| exprs.go:61:21:61:21 | lit-index 3 | exprs.go:61:21:61:21 | lit-init 3 |
13891382
| exprs.go:61:21:61:21 | lit-init 3 | exprs.go:61:9:61:22 | After slice literal |
13901383
| exprs.go:64:1:64:19 | After variable declaration | exprs.go:65:1:65:24 | variable declaration |
13911384
| exprs.go:64:1:64:19 | variable declaration | exprs.go:64:5:64:19 | value declaration specifier |

0 commit comments

Comments
 (0)