diff --git a/ql/src/InconsistentCode/InconsistentLoopOrientation.ql b/ql/src/InconsistentCode/InconsistentLoopOrientation.ql index 4e2978409f5..7eea9dbbeab 100644 --- a/ql/src/InconsistentCode/InconsistentLoopOrientation.ql +++ b/ql/src/InconsistentCode/InconsistentLoopOrientation.ql @@ -23,9 +23,9 @@ import go * downward. */ predicate bounds(RelationalComparisonExpr test, Variable v, string direction) { - test.getLesserOperand() = v.getAUse() and direction = "upward" + test.getLesserOperand() = v.getAReference() and direction = "upward" or - test.getGreaterOperand() = v.getAUse() and direction = "downward" + test.getGreaterOperand() = v.getAReference() and direction = "downward" } /** @@ -36,7 +36,7 @@ predicate bounds(RelationalComparisonExpr test, Variable v, string direction) { * downward. */ predicate updates(IncDecStmt upd, Variable v, string direction) { - upd.getExpr() = v.getAUse() and + upd.getExpr() = v.getAReference() and ( upd instanceof IncStmt and direction = "upward" or diff --git a/ql/src/RedundantCode/DeadStoreOfLocal.ql b/ql/src/RedundantCode/DeadStoreOfLocal.ql index 9e6bd8b9312..d6e7351a76d 100644 --- a/ql/src/RedundantCode/DeadStoreOfLocal.ql +++ b/ql/src/RedundantCode/DeadStoreOfLocal.ql @@ -36,7 +36,7 @@ where // exclude assignments with default values or simple expressions not isSimple(rhs) and // exclude variables that are not used at all - exists(target.getAUse()) and + exists(target.getAReference()) and // exclude variables with indirect references not target.mayHaveIndirectReferences() select def, "This definition of " + target + " is never used." diff --git a/ql/src/semmle/go/Scopes.qll b/ql/src/semmle/go/Scopes.qll index 4312439f480..e6817ec2034 100644 --- a/ql/src/semmle/go/Scopes.qll +++ b/ql/src/semmle/go/Scopes.qll @@ -116,9 +116,6 @@ class Entity extends @object { /** Gets the declaring identifier for this entity. */ Ident getDeclaration() { result.declares(this) } - /** Gets an identifier in rvalue position that refers to this entity. */ - Ident getAUse() { result.uses(this) } - /** Gets a reference to this entity. */ Name getAReference() { result.getTarget() = this } diff --git a/ql/src/semmle/go/controlflow/ControlFlowGraphImpl.qll b/ql/src/semmle/go/controlflow/ControlFlowGraphImpl.qll index 3dc5849a367..cd679dd6c63 100644 --- a/ql/src/semmle/go/controlflow/ControlFlowGraphImpl.qll +++ b/ql/src/semmle/go/controlflow/ControlFlowGraphImpl.qll @@ -114,9 +114,14 @@ newtype TControlFlowNode = ) or // in a return statement `return f()` where `f` has multiple return values - exists(ReturnStmt ret, CallExpr call | s = ret | - call = ret.getExpr().stripParens() and - exists(call.getType().(TupleType).getComponentType(i)) + exists(ReturnStmt ret, SignatureType rettp | + s = ret and + // the return statement has a single expression + exists(ret.getExpr()) and + // but the enclosing function has multiple results + rettp = ret.getEnclosingFunction().getType() and + rettp.getNumResult() > 1 and + exists(rettp.getResultType(i)) ) or // in a call `f(g())` where `g` has multiple return values diff --git a/ql/src/semmle/go/controlflow/IR.qll b/ql/src/semmle/go/controlflow/IR.qll index 0b37deadbbd..dc48d7300f9 100644 --- a/ql/src/semmle/go/controlflow/IR.qll +++ b/ql/src/semmle/go/controlflow/IR.qll @@ -50,16 +50,16 @@ module IR { } /** Holds if this instruction reads the value of variable or constant `v`. */ - predicate reads(ValueEntity v) { none() } + predicate reads(ValueEntity v) { readsField(_, v) or readsMethod(_, v) } /** Holds if this instruction updates variable or constant `v` to the value of `rhs`. */ - predicate writes(ValueEntity v, Instruction rhs) { none() } + predicate writes(ValueEntity v, Instruction rhs) { writesField(_, v, rhs) } /** Holds if this instruction reads the value of field `f` on the value of `base`. */ predicate readsField(Instruction base, Field f) { none() } /** Holds if this instruction updates the value of field `f` on the value of `base`. */ - predicate writesField(Instruction base, Field f) { none() } + predicate writesField(Instruction base, Field f, Instruction rhs) { none() } /** Holds if this instruction looks up method `m` on the value of `receiver`. */ predicate readsMethod(Instruction receiver, Method m) { none() } @@ -156,7 +156,7 @@ module IR { /** Gets the expression underlying this instruction. */ Expr getExpr() { result = e } - override predicate reads(ValueEntity v) { e = v.getAUse() } + override predicate reads(ValueEntity v) { e = v.getAReference() } override Type getResultType() { result = e.getType() } @@ -286,7 +286,7 @@ module IR { Instruction getRhs() { none() } override predicate writes(ValueEntity v, Instruction rhs) { - getLhs().(VarOrConstTarget).refersTo(v) and + getLhs().refersTo(v) and rhs = getRhs() } } @@ -398,9 +398,10 @@ module IR { /** Gets the field being written. */ Field getField() { result = lhs.getField() } - override predicate writesField(Instruction base, Field f) { + override predicate writesField(Instruction base, Field f, Instruction rhs) { getBase() = base and - getField() = f + getField() = f and + getRhs() = rhs } } @@ -1143,7 +1144,7 @@ module IR { } } - /** A representation of the target of of a write instruction. */ + /** A representation of the target of a write instruction. */ class WriteTarget extends TWriteTarget { ControlFlow::Node w; @@ -1160,6 +1161,9 @@ module IR { getWrite() = result.getDefinition().(SsaExplicitDefinition).getInstruction() } + /** Holds if `e` is the variable or field being written to. */ + predicate refersTo(ValueEntity e) { none() } + /** Gets a textual representation of this target. */ string toString() { result = "write target" } @@ -1196,8 +1200,7 @@ module IR { ) } - /** Holds if this is a reference to variable or constant `e`. */ - predicate refersTo(ValueEntity e) { + override predicate refersTo(ValueEntity e) { this instanceof MkLhs and loc = e.getAReference() or @@ -1254,11 +1257,10 @@ module IR { /** Get the type of the base of this field access, that is, the type that contains the field. */ Type getBaseType() { result = this.getBase().(EvalInstruction).getExpr().getType() } - /** Holds if this is a reference to variable or constant `e`. */ - predicate refersTo(Field f) { - exists(SelectorExpr sel | this = MkLhs(_, sel) | sel.getSelector() = f.getAReference()) + override predicate refersTo(ValueEntity e) { + exists(SelectorExpr sel | this = MkLhs(_, sel) | sel.uses(e)) or - f = w.(InitLiteralStructFieldInstruction).getField() + e = w.(InitLiteralStructFieldInstruction).getField() } override string getName() { exists(Field f | this.refersTo(f) | result = f.getName()) } diff --git a/ql/src/semmle/go/dataflow/GlobalValueNumbering.qll b/ql/src/semmle/go/dataflow/GlobalValueNumbering.qll index 312da3dd517..21ef8ea61cb 100644 --- a/ql/src/semmle/go/dataflow/GlobalValueNumbering.qll +++ b/ql/src/semmle/go/dataflow/GlobalValueNumbering.qll @@ -203,9 +203,7 @@ private newtype GVNBase = // guaranteed to have the same value. MkOtherVariable(ValueEntity x, ControlFlow::Node dominator) { mkOtherVariable(_, x, dominator) } or MkMethodAccess(GVN base, Function m) { mkMethodAccess(_, base, m) } or - MkFieldRead(GVN base, Variable f, ControlFlow::Node dominator) { - mkFieldRead(_, base, f, dominator) - } or + MkFieldRead(GVN base, Field f, ControlFlow::Node dominator) { mkFieldRead(_, base, f, dominator) } or MkPureCall(Function f, GVN callee, GVNList args) { mkPureCall(_, f, callee, args) } or MkIndex(GVN base, GVN index, ControlFlow::Node dominator) { mkIndex(_, base, index, dominator) } or // Dereference a pointer. The value might have changed since the last @@ -340,7 +338,10 @@ private predicate mkBoolConst(DataFlow::Node nd, boolean val) { nd.isPlatformIndependentConstant() } -private predicate mkFunc(DataFlow::Node nd, Function f) { nd = f.getARead() } +private predicate mkFunc(DataFlow::Node nd, Function f) { + nd = f.getARead() and + not f instanceof Method +} private predicate analyzableConst(DataFlow::Node e) { mkNumericConst(e, _) or mkStringConst(e, _) or mkBoolConst(e, _) or mkFunc(e, _) @@ -351,7 +352,7 @@ private predicate analyzableMethodAccess(Read access, DataFlow::Node receiver, M not access.isConst() } -private predicate mkMethodAccess(DataFlow::Node access, GVN qualifier, Function m) { +private predicate mkMethodAccess(DataFlow::Node access, GVN qualifier, Method m) { exists(DataFlow::Node base | analyzableMethodAccess(access, base, m) and qualifier = globalValueNumber(base) @@ -365,7 +366,7 @@ private predicate analyzableFieldRead(Read fread, DataFlow::Node base, Field f) } private predicate mkFieldRead( - DataFlow::Node fread, GVN qualifier, Variable v, ControlFlow::Node dominator + DataFlow::Node fread, GVN qualifier, Field v, ControlFlow::Node dominator ) { exists(DataFlow::Node base | analyzableFieldRead(fread, base, v) and @@ -393,12 +394,15 @@ private predicate mkPureCall(DataFlow::CallNode ce, Function f, GVN callee, GVNL * variables of non-primitive type (for which deep mutations are not captured by SSA). */ private predicate incompleteSsa(ValueEntity v) { - not v instanceof SsaSourceVariable - or - v.(SsaSourceVariable).mayHaveIndirectReferences() - or - exists(Type tp | tp = v.(DeclaredVariable).getType().getUnderlyingType() | - not tp instanceof BasicType + not v instanceof Field and + ( + not v instanceof SsaSourceVariable + or + v.(SsaSourceVariable).mayHaveIndirectReferences() + or + exists(Type tp | tp = v.(DeclaredVariable).getType().getUnderlyingType() | + not tp instanceof BasicType + ) ) } diff --git a/ql/src/semmle/go/dataflow/SSA.qll b/ql/src/semmle/go/dataflow/SSA.qll index 3add50eb220..da3303d24b5 100644 --- a/ql/src/semmle/go/dataflow/SSA.qll +++ b/ql/src/semmle/go/dataflow/SSA.qll @@ -22,7 +22,7 @@ class SsaSourceVariable extends LocalVariable { */ predicate mayHaveIndirectReferences() { // variables that have their address taken - exists(AddressExpr addr | addr.getOperand().stripParens() = getAUse()) + exists(AddressExpr addr | addr.getOperand().stripParens() = getAReference()) or exists(DataFlow::MethodReadNode mrn | mrn.getReceiver() = getARead() and diff --git a/ql/src/semmle/go/dataflow/internal/DataFlowPrivate.qll b/ql/src/semmle/go/dataflow/internal/DataFlowPrivate.qll index 9651dd64840..7f000ba82cb 100644 --- a/ql/src/semmle/go/dataflow/internal/DataFlowPrivate.qll +++ b/ql/src/semmle/go/dataflow/internal/DataFlowPrivate.qll @@ -72,6 +72,7 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { predicate jumpStep(Node n1, Node n2) { exists(ValueEntity v, Write w | not v instanceof SsaSourceVariable and + not v instanceof Field and w.writes(v, n1) and n2 = v.getARead() ) diff --git a/ql/test/library-tests/semmle/go/Scopes/DeclaredEntity.expected b/ql/test/library-tests/semmle/go/Scopes/DeclaredEntity.expected index a16a67556b2..d42748fe81b 100644 --- a/ql/test/library-tests/semmle/go/Scopes/DeclaredEntity.expected +++ b/ql/test/library-tests/semmle/go/Scopes/DeclaredEntity.expected @@ -1,4 +1,5 @@ | a | types.go:24:22:24:22 | a | +| bump | main.go:23:16:23:19 | bump | | foo | main.go:17:6:17:8 | foo | | iHaveAMethod | types.go:3:6:3:17 | iHaveAMethod | | main | main.go:9:6:9:9 | main | @@ -12,6 +13,7 @@ | meth2 | types.go:28:16:28:20 | meth2 | | notImpl | types.go:22:6:22:12 | notImpl | | recv | main.go:13:7:13:10 | recv | +| recv | main.go:23:7:23:10 | recv | | starImpl | types.go:12:6:12:13 | starImpl | | t | main.go:5:6:5:6 | t | | twoMethods | types.go:7:6:7:15 | twoMethods | diff --git a/ql/test/library-tests/semmle/go/Scopes/EntityRead.expected b/ql/test/library-tests/semmle/go/Scopes/EntityRead.expected new file mode 100644 index 00000000000..c67c623658b --- /dev/null +++ b/ql/test/library-tests/semmle/go/Scopes/EntityRead.expected @@ -0,0 +1,13 @@ +| Println | main.go:10:2:10:12 | selection of Println | +| a | types.go:25:9:25:9 | a | +| false | types.go:15:9:15:13 | false | +| meth | main.go:18:2:18:7 | selection of meth | +| meth | main.go:19:2:19:7 | selection of meth | +| meth | main.go:20:2:20:10 | selection of meth | +| recv | main.go:14:9:14:12 | recv | +| recv | main.go:24:2:24:5 | recv | +| x | main.go:14:9:14:14 | selection of x | +| x | main.go:18:2:18:2 | x | +| x | main.go:24:2:24:7 | selection of x | +| y | main.go:19:2:19:2 | y | +| y | main.go:20:12:20:12 | y | diff --git a/ql/test/library-tests/semmle/go/Scopes/EntityRead.ql b/ql/test/library-tests/semmle/go/Scopes/EntityRead.ql new file mode 100644 index 00000000000..7638ac92971 --- /dev/null +++ b/ql/test/library-tests/semmle/go/Scopes/EntityRead.ql @@ -0,0 +1,4 @@ +import go + +from ValueEntity e +select e, e.getARead() diff --git a/ql/test/library-tests/semmle/go/Scopes/EntityReference.expected b/ql/test/library-tests/semmle/go/Scopes/EntityReference.expected new file mode 100644 index 00000000000..eb3c1419a3e --- /dev/null +++ b/ql/test/library-tests/semmle/go/Scopes/EntityReference.expected @@ -0,0 +1,61 @@ +| Println | | main.go:10:2:10:12 | selection of Println | +| Println | | main.go:10:6:10:12 | Println | +| a | types.go@24:22-24:22 | types.go:24:22:24:22 | a | +| a | types.go@24:22-24:22 | types.go:25:9:25:9 | a | +| bool | | types.go:8:10:8:13 | bool | +| bool | | types.go:14:26:14:29 | bool | +| bool | | types.go:24:29:24:32 | bool | +| bump | main.go@23:16-23:19 | main.go:23:16:23:19 | bump | +| false | | types.go:15:9:15:13 | false | +| fmt | | main.go:10:2:10:4 | fmt | +| foo | main.go@17:6-17:8 | main.go:17:6:17:8 | foo | +| iHaveAMethod | types.go@3:6-3:17 | main.go:17:12:17:23 | iHaveAMethod | +| iHaveAMethod | types.go@3:6-3:17 | types.go:3:6:3:17 | iHaveAMethod | +| int | | main.go:6:4:6:6 | int | +| int | | main.go:13:23:13:25 | int | +| int | | types.go:4:9:4:11 | int | +| int | | types.go:9:10:9:12 | int | +| int | | types.go:18:25:18:27 | int | +| int | | types.go:24:24:24:26 | int | +| int | | types.go:28:24:28:26 | int | +| main | main.go@9:6-9:9 | main.go:9:6:9:9 | main | +| meth | main.go@13:16-13:19 | main.go:13:16:13:19 | meth | +| meth | main.go@13:16-13:19 | main.go:19:2:19:7 | selection of meth | +| meth | main.go@13:16-13:19 | main.go:19:4:19:7 | meth | +| meth | main.go@13:16-13:19 | main.go:20:2:20:10 | selection of meth | +| meth | main.go@13:16-13:19 | main.go:20:7:20:10 | meth | +| meth | types.go@4:2-4:5 | main.go:18:2:18:7 | selection of meth | +| meth | types.go@4:2-4:5 | main.go:18:4:18:7 | meth | +| meth | types.go@4:2-4:5 | types.go:4:2:4:5 | meth | +| meth1 | types.go@8:2-8:6 | types.go:8:2:8:6 | meth1 | +| meth1 | types.go@14:18-14:22 | types.go:14:18:14:22 | meth1 | +| meth1 | types.go@24:16-24:20 | types.go:24:16:24:20 | meth1 | +| meth2 | types.go@9:2-9:6 | types.go:9:2:9:6 | meth2 | +| meth2 | types.go@18:17-18:21 | types.go:18:17:18:21 | meth2 | +| meth2 | types.go@28:16-28:20 | types.go:28:16:28:20 | meth2 | +| notImpl | types.go@22:6-22:12 | types.go:22:6:22:12 | notImpl | +| notImpl | types.go@22:6-22:12 | types.go:24:7:24:13 | notImpl | +| notImpl | types.go@22:6-22:12 | types.go:28:7:28:13 | notImpl | +| recv | main.go@13:7-13:10 | main.go:13:7:13:10 | recv | +| recv | main.go@13:7-13:10 | main.go:14:9:14:12 | recv | +| recv | main.go@23:7-23:10 | main.go:23:7:23:10 | recv | +| recv | main.go@23:7-23:10 | main.go:24:2:24:5 | recv | +| starImpl | types.go@12:6-12:13 | types.go:12:6:12:13 | starImpl | +| starImpl | types.go@12:6-12:13 | types.go:14:8:14:15 | starImpl | +| starImpl | types.go@12:6-12:13 | types.go:18:7:18:14 | starImpl | +| t | main.go@5:6-5:6 | main.go:5:6:5:6 | t | +| t | main.go@5:6-5:6 | main.go:13:13:13:13 | t | +| t | main.go@5:6-5:6 | main.go:17:29:17:29 | t | +| t | main.go@5:6-5:6 | main.go:20:4:20:4 | t | +| t | main.go@5:6-5:6 | main.go:23:13:23:13 | t | +| twoMethods | types.go@7:6-7:15 | types.go:7:6:7:15 | twoMethods | +| x | main.go@6:2-6:2 | main.go:6:2:6:2 | x | +| x | main.go@6:2-6:2 | main.go:14:9:14:14 | selection of x | +| x | main.go@6:2-6:2 | main.go:14:14:14:14 | x | +| x | main.go@6:2-6:2 | main.go:24:2:24:7 | selection of x | +| x | main.go@6:2-6:2 | main.go:24:7:24:7 | x | +| x | main.go@17:10-17:10 | main.go:17:10:17:10 | x | +| x | main.go@17:10-17:10 | main.go:18:2:18:2 | x | +| y | main.go@17:26-17:26 | main.go:17:26:17:26 | y | +| y | main.go@17:26-17:26 | main.go:19:2:19:2 | y | +| y | main.go@17:26-17:26 | main.go:20:12:20:12 | y | diff --git a/ql/test/library-tests/semmle/go/Scopes/EntityUse.ql b/ql/test/library-tests/semmle/go/Scopes/EntityReference.ql similarity index 83% rename from ql/test/library-tests/semmle/go/Scopes/EntityUse.ql rename to ql/test/library-tests/semmle/go/Scopes/EntityReference.ql index 7e893263bc0..687bf55dcaa 100644 --- a/ql/test/library-tests/semmle/go/Scopes/EntityUse.ql +++ b/ql/test/library-tests/semmle/go/Scopes/EntityReference.ql @@ -6,4 +6,4 @@ where or not exists(e.getDeclaration()) and declloc = "" -select e, declloc, e.getAUse() +select e, declloc, e.getAReference() diff --git a/ql/test/library-tests/semmle/go/Scopes/EntityType.expected b/ql/test/library-tests/semmle/go/Scopes/EntityType.expected index 96b5059f30c..c58957716c3 100644 --- a/ql/test/library-tests/semmle/go/Scopes/EntityType.expected +++ b/ql/test/library-tests/semmle/go/Scopes/EntityType.expected @@ -1,4 +1,5 @@ | a | int | +| bump | func() | | foo | func(iHaveAMethod, * t) | | iHaveAMethod | iHaveAMethod | | main | func() | @@ -12,6 +13,7 @@ | meth2 | func() int | | notImpl | notImpl | | recv | * t | +| recv | * t | | starImpl | starImpl | | t | t | | twoMethods | twoMethods | diff --git a/ql/test/library-tests/semmle/go/Scopes/EntityUse.expected b/ql/test/library-tests/semmle/go/Scopes/EntityUse.expected deleted file mode 100644 index 2ca658ffae9..00000000000 --- a/ql/test/library-tests/semmle/go/Scopes/EntityUse.expected +++ /dev/null @@ -1,30 +0,0 @@ -| Println | | main.go:10:6:10:12 | Println | -| a | types.go@24:22-24:22 | types.go:25:9:25:9 | a | -| bool | | types.go:8:10:8:13 | bool | -| bool | | types.go:14:26:14:29 | bool | -| bool | | types.go:24:29:24:32 | bool | -| false | | types.go:15:9:15:13 | false | -| fmt | | main.go:10:2:10:4 | fmt | -| iHaveAMethod | types.go@3:6-3:17 | main.go:17:12:17:23 | iHaveAMethod | -| int | | main.go:6:4:6:6 | int | -| int | | main.go:13:23:13:25 | int | -| int | | types.go:4:9:4:11 | int | -| int | | types.go:9:10:9:12 | int | -| int | | types.go:18:25:18:27 | int | -| int | | types.go:24:24:24:26 | int | -| int | | types.go:28:24:28:26 | int | -| meth | main.go@13:16-13:19 | main.go:19:4:19:7 | meth | -| meth | main.go@13:16-13:19 | main.go:20:7:20:10 | meth | -| meth | types.go@4:2-4:5 | main.go:18:4:18:7 | meth | -| notImpl | types.go@22:6-22:12 | types.go:24:7:24:13 | notImpl | -| notImpl | types.go@22:6-22:12 | types.go:28:7:28:13 | notImpl | -| recv | main.go@13:7-13:10 | main.go:14:9:14:12 | recv | -| starImpl | types.go@12:6-12:13 | types.go:14:8:14:15 | starImpl | -| starImpl | types.go@12:6-12:13 | types.go:18:7:18:14 | starImpl | -| t | main.go@5:6-5:6 | main.go:13:13:13:13 | t | -| t | main.go@5:6-5:6 | main.go:17:29:17:29 | t | -| t | main.go@5:6-5:6 | main.go:20:4:20:4 | t | -| x | main.go@6:2-6:2 | main.go:14:14:14:14 | x | -| x | main.go@17:10-17:10 | main.go:18:2:18:2 | x | -| y | main.go@17:26-17:26 | main.go:19:2:19:2 | y | -| y | main.go@17:26-17:26 | main.go:20:12:20:12 | y | diff --git a/ql/test/library-tests/semmle/go/Scopes/EntityWrite.expected b/ql/test/library-tests/semmle/go/Scopes/EntityWrite.expected new file mode 100644 index 00000000000..684399838ee --- /dev/null +++ b/ql/test/library-tests/semmle/go/Scopes/EntityWrite.expected @@ -0,0 +1,6 @@ +| a | types.go:24:22:24:22 | initialization of a | +| recv | main.go:13:7:13:10 | initialization of recv | +| recv | main.go:23:7:23:10 | initialization of recv | +| x | main.go:17:10:17:10 | initialization of x | +| x | main.go:24:2:24:9 | increment statement | +| y | main.go:17:26:17:26 | initialization of y | diff --git a/ql/test/library-tests/semmle/go/Scopes/EntityWrite.ql b/ql/test/library-tests/semmle/go/Scopes/EntityWrite.ql new file mode 100644 index 00000000000..f0627ef37ca --- /dev/null +++ b/ql/test/library-tests/semmle/go/Scopes/EntityWrite.ql @@ -0,0 +1,4 @@ +import go + +from ValueEntity e +select e, e.getAWrite() diff --git a/ql/test/library-tests/semmle/go/Scopes/Methods.expected b/ql/test/library-tests/semmle/go/Scopes/Methods.expected index ec4fb1aabde..baaf7d3065b 100644 --- a/ql/test/library-tests/semmle/go/Scopes/Methods.expected +++ b/ql/test/library-tests/semmle/go/Scopes/Methods.expected @@ -1,3 +1,4 @@ +| bump | github.com/Semmle/go/ql/test/library-tests/semmle/go/Scopes.t.bump | recv | * t | | meth | github.com/Semmle/go/ql/test/library-tests/semmle/go/Scopes.iHaveAMethod.meth | | iHaveAMethod | | meth | github.com/Semmle/go/ql/test/library-tests/semmle/go/Scopes.t.meth | recv | * t | | meth1 | github.com/Semmle/go/ql/test/library-tests/semmle/go/Scopes.notImpl.meth1 | | notImpl | diff --git a/ql/test/library-tests/semmle/go/Scopes/main.go b/ql/test/library-tests/semmle/go/Scopes/main.go index e1a9bab9845..294255b275d 100644 --- a/ql/test/library-tests/semmle/go/Scopes/main.go +++ b/ql/test/library-tests/semmle/go/Scopes/main.go @@ -19,3 +19,7 @@ func foo(x iHaveAMethod, y *t) { y.meth() (*t).meth(y) } + +func (recv *t) bump() { + recv.x++ +} diff --git a/ql/test/library-tests/semmle/go/dataflow/GlobalValueNumbering/GlobalValueNumber.expected b/ql/test/library-tests/semmle/go/dataflow/GlobalValueNumbering/GlobalValueNumber.expected index cf57f7204f0..93b3593ec94 100644 --- a/ql/test/library-tests/semmle/go/dataflow/GlobalValueNumbering/GlobalValueNumber.expected +++ b/ql/test/library-tests/semmle/go/dataflow/GlobalValueNumbering/GlobalValueNumber.expected @@ -40,3 +40,5 @@ | regressions.go:7:11:7:15 | false | regressions.go:7:11:7:15 | false | | regressions.go:9:11:9:12 | !... | regressions.go:11:11:11:14 | true | | regressions.go:11:11:11:14 | true | regressions.go:11:11:11:14 | true | +| regressions.go:30:9:30:22 | call to getPayload | regressions.go:30:9:30:22 | call to getPayload | +| regressions.go:30:26:30:39 | call to getPayload | regressions.go:30:26:30:39 | call to getPayload | diff --git a/ql/test/library-tests/semmle/go/dataflow/GlobalValueNumbering/regressions.go b/ql/test/library-tests/semmle/go/dataflow/GlobalValueNumbering/regressions.go index 0388d289d4e..15b58c52147 100644 --- a/ql/test/library-tests/semmle/go/dataflow/GlobalValueNumbering/regressions.go +++ b/ql/test/library-tests/semmle/go/dataflow/GlobalValueNumbering/regressions.go @@ -9,3 +9,23 @@ const d = false const e = !d const f = true + +type cell struct { + payload int + next *cell +} + +func test4(x, y cell) int { + return x.payload + + y.payload + + x.next.payload + + y.next.payload +} + +func (c *cell) getPayload() int { + return c.payload +} + +func test5(x, y cell) int { + return x.getPayload() + y.getPayload() +} diff --git a/ql/test/library-tests/semmle/go/dataflow/SSA/VarUses.expected b/ql/test/library-tests/semmle/go/dataflow/SSA/VarUses.expected index b6cd184ce8c..4e8d3608c2e 100644 --- a/ql/test/library-tests/semmle/go/dataflow/SSA/VarUses.expected +++ b/ql/test/library-tests/semmle/go/dataflow/SSA/VarUses.expected @@ -27,4 +27,5 @@ | main.go:84:9:84:9 | x | x | | main.go:84:15:84:15 | x | x | | main.go:94:2:94:8 | wrapper | wrapper | +| main.go:94:2:94:10 | selection of s | s | | main.go:97:9:97:9 | x | x | diff --git a/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/main.go b/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/main.go index 3bb3c390ae0..31062a18f98 100644 --- a/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/main.go +++ b/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/main.go @@ -31,3 +31,7 @@ func test2(x int) (int, int) { z := x % (1) return z, y % 13 } + +func test3() (x int, y int) { + return unknownFunction() +}