diff --git a/go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll b/go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll index 76254e963d3..7a4db67f273 100644 --- a/go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll +++ b/go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll @@ -587,14 +587,6 @@ module GoCfg { n = any(Go::CompositeLit lit).getAnElement() and tag = "lit-init" or - // Implicit literal element index - exists(Go::CompositeLit lit | - not lit instanceof Go::StructLit and - n = lit.getAnElement() and - not n instanceof Go::KeyValueExpr and - tag = "lit-index" - ) - or // Implicit field selection for promoted fields exists(int i, Go::Field implicitField | implicitFieldSelection(n, i, implicitField) and @@ -1480,17 +1472,12 @@ module GoCfg { not exists(lit.getElement(_)) and n2.isAfter(lit) ) or - // After element → optional lit-index → lit-init → next element or After + // After element → lit-init → next element or After. + // Positional array/slice elements have an implicit index that is + // modelled on the `lit-init` instruction itself (see + // `IR::InitLiteralElementInstruction`) rather than as a separate node. exists(int i | n1.isAfter(lit.getElement(i)) and - ( - n2.isAdditional(lit.getElement(i), "lit-index") - or - not exists(PreControlFlowNode idx | idx.isAdditional(lit.getElement(i), "lit-index")) and - n2.isAdditional(lit.getElement(i), "lit-init") - ) - or - n1.isAdditional(lit.getElement(i), "lit-index") and n2.isAdditional(lit.getElement(i), "lit-init") or n1.isAdditional(lit.getElement(i), "lit-init") and diff --git a/go/ql/lib/semmle/go/controlflow/IR.qll b/go/ql/lib/semmle/go/controlflow/IR.qll index fce3f5f5873..c860ce1908d 100644 --- a/go/ql/lib/semmle/go/controlflow/IR.qll +++ b/go/ql/lib/semmle/go/controlflow/IR.qll @@ -159,8 +159,6 @@ module IR { or this instanceof InitLiteralComponentInstruction and result = "element init" or - this instanceof ImplicitLiteralElementIndexInstruction and result = "element index" - or this instanceof AssignInstruction and result = "assignment" or this instanceof EvalCompoundAssignRhsInstruction and @@ -578,7 +576,11 @@ module IR { Instruction getIndex() { result = evalExprInstruction(elt.(KeyValueExpr).getKey()) or - result.(ImplicitLiteralElementIndexInstruction).isAdditional(elt, "lit-index") + // A positional array/slice element has an implicit index. Array/slice + // content flow is index-insensitive, so rather than materialise a + // separate index node the element-init instruction acts as its own + // (opaque) index. + not elt instanceof KeyValueExpr and result = this } } @@ -627,54 +629,6 @@ module IR { } } - private predicate noExplicitKeys(CompositeLit lit) { - not lit.getAnElement() instanceof KeyValueExpr - } - - private int getElementIndex(CompositeLit lit, int i) { - ( - lit.getType().getUnderlyingType() instanceof ArrayType or - lit.getType().getUnderlyingType() instanceof SliceType - ) and - exists(Expr elt | elt = lit.getElement(i) | - noExplicitKeys(lit) and result = i - or - result = elt.(KeyValueExpr).getKey().getIntValue() - or - not elt instanceof KeyValueExpr and - ( - i = 0 and result = 0 - or - result = getElementIndex(lit, i - 1) + 1 - ) - ) - } - - /** - * An IR instruction computing the implicit index of an element in an array or slice literal. - */ - class ImplicitLiteralElementIndexInstruction extends Instruction { - Expr elt; - - ImplicitLiteralElementIndexInstruction() { this.isAdditional(elt, "lit-index") } - - override Type getResultType() { result instanceof IntType } - - override ControlFlow::Root getRoot() { result.isRootOf(elt) } - - override int getIntValue() { - exists(CompositeLit lit, int i | elt = lit.getElement(i) | result = getElementIndex(lit, i)) - } - - override string getStringValue() { none() } - - override string getExactValue() { result = this.getIntValue().toString() } - - override predicate isPlatformIndependentConstant() { any() } - - override predicate isConst() { any() } - } - /** * An instruction assigning to a variable or field. */ diff --git a/go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/ControlFlowNode_getASuccessor.expected b/go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/ControlFlowNode_getASuccessor.expected index 79d00c2af2a..3a6dab6b52f 100644 --- a/go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/ControlFlowNode_getASuccessor.expected +++ b/go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/ControlFlowNode_getASuccessor.expected @@ -969,9 +969,8 @@ | exprs.go:16:17:16:23 | After struct3 | exprs.go:16:17:16:25 | selection of x | | exprs.go:16:17:16:23 | Before struct3 | exprs.go:16:17:16:23 | struct3 | | exprs.go:16:17:16:23 | struct3 | exprs.go:16:17:16:23 | After struct3 | -| exprs.go:16:17:16:25 | After selection of x | exprs.go:16:17:16:25 | lit-index selection of x | +| exprs.go:16:17:16:25 | After selection of x | exprs.go:16:17:16:25 | lit-init selection of x | | exprs.go:16:17:16:25 | Before selection of x | exprs.go:16:17:16:23 | Before struct3 | -| exprs.go:16:17:16:25 | lit-index selection of x | exprs.go:16:17:16:25 | lit-init selection of x | | exprs.go:16:17:16:25 | lit-init selection of x | exprs.go:16:10:16:26 | After array literal | | exprs.go:16:17:16:25 | selection of x | exprs.go:16:17:16:25 | After selection of x | | exprs.go:17:2:17:40 | ... := ... | exprs.go:17:10:17:40 | Before array literal | @@ -983,9 +982,8 @@ | exprs.go:17:19:17:25 | After struct3 | exprs.go:17:19:17:27 | selection of x | | exprs.go:17:19:17:25 | Before struct3 | exprs.go:17:19:17:25 | struct3 | | exprs.go:17:19:17:25 | struct3 | exprs.go:17:19:17:25 | After struct3 | -| exprs.go:17:19:17:27 | After selection of x | exprs.go:17:19:17:27 | lit-index selection of x | +| exprs.go:17:19:17:27 | After selection of x | exprs.go:17:19:17:27 | lit-init selection of x | | exprs.go:17:19:17:27 | Before selection of x | exprs.go:17:19:17:25 | Before struct3 | -| exprs.go:17:19:17:27 | lit-index selection of x | exprs.go:17:19:17:27 | lit-init selection of x | | exprs.go:17:19:17:27 | lit-init selection of x | exprs.go:17:30:17:39 | Before key-value pair | | exprs.go:17:19:17:27 | selection of x | exprs.go:17:19:17:27 | After selection of x | | exprs.go:17:30:17:30 | 2 | exprs.go:17:30:17:30 | After 2 | @@ -1011,14 +1009,12 @@ | exprs.go:18:9:18:22 | After slice literal | exprs.go:18:2:18:22 | assign:0 ... := ... | | exprs.go:18:9:18:22 | Before slice literal | exprs.go:18:9:18:22 | slice literal | | exprs.go:18:9:18:22 | slice literal | exprs.go:18:18:18:18 | Before s | -| exprs.go:18:18:18:18 | After s | exprs.go:18:18:18:18 | lit-index s | +| exprs.go:18:18:18:18 | After s | exprs.go:18:18:18:18 | lit-init s | | exprs.go:18:18:18:18 | Before s | exprs.go:18:18:18:18 | s | -| exprs.go:18:18:18:18 | lit-index s | exprs.go:18:18:18:18 | lit-init s | | exprs.go:18:18:18:18 | lit-init s | exprs.go:18:21:18:21 | Before s | | exprs.go:18:18:18:18 | s | exprs.go:18:18:18:18 | After s | -| exprs.go:18:21:18:21 | After s | exprs.go:18:21:18:21 | lit-index s | +| exprs.go:18:21:18:21 | After s | exprs.go:18:21:18:21 | lit-init s | | exprs.go:18:21:18:21 | Before s | exprs.go:18:21:18:21 | s | -| exprs.go:18:21:18:21 | lit-index s | exprs.go:18:21:18:21 | lit-init s | | exprs.go:18:21:18:21 | lit-init s | exprs.go:18:9:18:22 | After slice literal | | exprs.go:18:21:18:21 | s | exprs.go:18:21:18:21 | After s | | exprs.go:19:2:19:38 | ... := ... | exprs.go:19:8:19:38 | Before map literal | @@ -1373,19 +1369,16 @@ | exprs.go:61:9:61:22 | Before slice literal | exprs.go:61:9:61:22 | slice literal | | exprs.go:61:9:61:22 | slice literal | exprs.go:61:15:61:15 | Before 1 | | exprs.go:61:15:61:15 | 1 | exprs.go:61:15:61:15 | After 1 | -| exprs.go:61:15:61:15 | After 1 | exprs.go:61:15:61:15 | lit-index 1 | +| exprs.go:61:15:61:15 | After 1 | exprs.go:61:15:61:15 | lit-init 1 | | exprs.go:61:15:61:15 | Before 1 | exprs.go:61:15:61:15 | 1 | -| exprs.go:61:15:61:15 | lit-index 1 | exprs.go:61:15:61:15 | lit-init 1 | | exprs.go:61:15:61:15 | lit-init 1 | exprs.go:61:18:61:18 | Before 2 | | exprs.go:61:18:61:18 | 2 | exprs.go:61:18:61:18 | After 2 | -| exprs.go:61:18:61:18 | After 2 | exprs.go:61:18:61:18 | lit-index 2 | +| exprs.go:61:18:61:18 | After 2 | exprs.go:61:18:61:18 | lit-init 2 | | exprs.go:61:18:61:18 | Before 2 | exprs.go:61:18:61:18 | 2 | -| exprs.go:61:18:61:18 | lit-index 2 | exprs.go:61:18:61:18 | lit-init 2 | | exprs.go:61:18:61:18 | lit-init 2 | exprs.go:61:21:61:21 | Before 3 | | exprs.go:61:21:61:21 | 3 | exprs.go:61:21:61:21 | After 3 | -| exprs.go:61:21:61:21 | After 3 | exprs.go:61:21:61:21 | lit-index 3 | +| exprs.go:61:21:61:21 | After 3 | exprs.go:61:21:61:21 | lit-init 3 | | exprs.go:61:21:61:21 | Before 3 | exprs.go:61:21:61:21 | 3 | -| exprs.go:61:21:61:21 | lit-index 3 | exprs.go:61:21:61:21 | lit-init 3 | | exprs.go:61:21:61:21 | lit-init 3 | exprs.go:61:9:61:22 | After slice literal | | exprs.go:64:1:64:19 | After variable declaration | exprs.go:65:1:65:24 | variable declaration | | exprs.go:64:1:64:19 | variable declaration | exprs.go:64:5:64:19 | value declaration specifier |