Skip to content

Commit 1154db4

Browse files
authored
Merge pull request #21957 from owen-mc/go/fix-result-node
Go: fix `DataFlow::ResultNode` and some related things
2 parents 6161922 + 0a065c9 commit 1154db4

13 files changed

Lines changed: 235 additions & 124 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: deprecated
3+
---
4+
* `FuncTypeExpr.getResultDecl()` has been deprecated. Use `FuncTypeExpr.getResultDecl(int i)` instead.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* `DataFlow::ResultNode`s are no longer created for returned expressions in functions with named result parameters. In this case there are already result nodes corresponding to `IR::ReadResultInstruction`s at the end of the function body.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* `FuncTypeExpr.getNumResult()` now gets the number of result parameters. It previously got the number of result declarations, which is different when one result declaration declares more than one variable, as in `x, y int`. All uses of it expected the number of result parameters. Its QLDoc has been updated.

go/ql/lib/semmle/go/Expr.qll

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,17 +1049,29 @@ class FuncTypeExpr extends @functypeexpr, TypeExpr, ScopeNode, FieldParent {
10491049
*/
10501050
int getNumParameter() { result = count(this.getAParameterDecl().getANameExpr()) }
10511051

1052-
/** Gets the `i`th result of this function type (0-based). */
1052+
/**
1053+
* Gets the `i`th result declaration of this function type (0-based).
1054+
*
1055+
* Note: `x, y int` is a single `ResultVariableDecl`.
1056+
*/
10531057
ResultVariableDecl getResultDecl(int i) { result = this.getField(-(i + 1)) }
10541058

1055-
/** Gets a result of this function type. */
1059+
/**
1060+
* Gets a result declaration of this function type.
1061+
*
1062+
* Note: `x, y int` is a single `ResultVariableDecl`.
1063+
*/
10561064
ResultVariableDecl getAResultDecl() { result = this.getResultDecl(_) }
10571065

1058-
/** Gets the number of results of this function type. */
1059-
int getNumResult() { result = count(this.getAResultDecl()) }
1066+
/** Gets the number of result parameters of this function type. */
1067+
int getNumResult() { result = count(this.getAResultDecl().getANameExpr()) }
10601068

1061-
/** Gets the result of this function type, if there is only one. */
1062-
ResultVariableDecl getResultDecl() { this.getNumResult() = 1 and result = this.getAResultDecl() }
1069+
/**
1070+
* DEPRECATED: Use `getResultDecl(int i)` instead.
1071+
*/
1072+
deprecated ResultVariableDecl getResultDecl() {
1073+
this.getNumResult() = 1 and result = this.getAResultDecl()
1074+
}
10631075

10641076
override string toString() { result = "function type" }
10651077

go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -923,15 +923,20 @@ module Public {
923923
/**
924924
* A node whose value is returned as a result from a function.
925925
*
926-
* This can either be a node corresponding to an expression in a return statement,
927-
* or a node representing the current value of a named result variable at the exit
928-
* of the function.
926+
* If the function declares named result variables, this is a node representing
927+
* the current value of one of those variables at function exit. Otherwise, this
928+
* is a node corresponding to an expression in a return statement.
929929
*/
930930
class ResultNode extends InstructionNode {
931931
int i;
932932

933933
ResultNode() {
934934
exists(FuncDef fd |
935+
// If the function has named result variables, then the
936+
// `IR::ReadResultInstruction` nodes at the end of the function are
937+
// the correct result nodes. Otherwise, the returned expressions are
938+
// the result nodes.
939+
not exists(fd.getAResultVar()) and
935940
exists(IR::ReturnInstruction ret | ret.getRoot() = fd | insn = ret.getResult(i))
936941
or
937942
insn.(IR::ReadResultInstruction).reads(fd.getResultVar(i))

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

Lines changed: 138 additions & 114 deletions
Large diffs are not rendered by default.

go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/main.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ func baz2() (result int) {
5353
return
5454
}
5555

56+
func baz3(selector int) (result int) {
57+
result = 0
58+
if selector == 1 {
59+
return 1
60+
} else {
61+
result = 2
62+
}
63+
return
64+
}
65+
5666
func loops() {
5767
var x int
5868
for cond() {

go/ql/test/library-tests/semmle/go/dataflow/Nodes/BinaryOperationNodes.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
| main.go:7:19:7:23 | ...+... | + | main.go:7:19:7:19 | y | main.go:7:23:7:23 | z |
33
| main.go:10:14:10:18 | ...+... | + | main.go:10:14:10:14 | x | main.go:10:18:10:18 | y |
44
| main.go:17:2:17:13 | ... += ... | + | main.go:17:2:17:6 | index expression | main.go:17:11:17:13 | "!" |
5+
| resultParameters.go:4:5:4:17 | ...==... | == | resultParameters.go:4:5:4:12 | selector | resultParameters.go:4:17:4:17 | 0 |
6+
| resultParameters.go:23:5:23:17 | ...==... | == | resultParameters.go:23:5:23:12 | selector | resultParameters.go:23:17:23:17 | 1 |
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
| main.go:21:9:21:10 | 23 | Result node with index 0 |
2+
| main.go:21:13:21:14 | 42 | Result node with index 1 |
3+
| resultParameters.go:5:10:5:10 | 0 | Result node with index 0 |
4+
| resultParameters.go:9:10:9:10 | 1 | Result node with index 0 |
5+
| resultParameters.go:11:10:11:10 | 2 | Result node with index 0 |
6+
| resultParameters.go:13:9:13:9 | 3 | Result node with index 0 |
7+
| resultParameters.go:16:26:16:26 | implicit read of r | Result node with index 0 |
8+
| resultParameters.go:21:38:21:38 | implicit read of r | Result node with index 0 |
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* @kind problem
3+
* @id result-node
4+
*/
5+
6+
import go
7+
8+
from DataFlow::ResultNode r
9+
select r, "Result node with index " + r.getIndex()

0 commit comments

Comments
 (0)