mirror of
https://github.com/github/codeql.git
synced 2026-08-01 07:53:00 +02:00
fold compound-assign write into the compound-rhs instruction
A compound assignment (`x += y`) previously produced two sequential control-flow nodes: a 'compound-rhs' node computing the binary operation `x + y`, followed by an 'assign:0' write node storing the result. Make the compound-rhs instruction itself perform the write (it becomes a WriteInstruction whose right-hand side is its own value), and stop emitting the separate assign:0 node for compound assignments. This saves one CFG node per compound assignment while preserving the BinaryOperationNode model (so string-concatenation taint through `s += ...` still holds) and SSA semantics (the def value is the binary operation).
This commit is contained in:
@@ -502,6 +502,11 @@ module GoCfg {
|
||||
exists(int i |
|
||||
(
|
||||
notBlankIdent(n.(Go::Assignment).getLhs(i)) and
|
||||
// A compound assignment (`x += y`) folds its write into the
|
||||
// `compound-rhs` binary-operation instruction rather than emitting a
|
||||
// separate `assign:i` write node (see
|
||||
// `IR::EvalCompoundAssignRhsInstruction`).
|
||||
not n instanceof Go::CompoundAssignStmt and
|
||||
// The `y := x.(type)` test statement of a type switch is transparent
|
||||
// (see `skipCfg`): the per-case implicit variables are written at the
|
||||
// case match nodes (see `IR::TypeSwitchImplicitVariableInstruction`),
|
||||
@@ -1139,7 +1144,10 @@ module GoCfg {
|
||||
)
|
||||
or
|
||||
(
|
||||
notBlankIdent(assgn.(Go::Assignment).getLhs(j))
|
||||
notBlankIdent(assgn.(Go::Assignment).getLhs(j)) and
|
||||
// Compound assignments fold their write into `compound-rhs` (ord -1)
|
||||
// above, so they emit no separate `assign:j` node.
|
||||
not assgn instanceof Go::CompoundAssignStmt
|
||||
or
|
||||
notBlankIdent(assgn.(Go::ValueSpec).getNameExpr(j))
|
||||
or
|
||||
|
||||
@@ -726,8 +726,6 @@ module IR {
|
||||
implicitInitInstruction(any(ValueEntity v | spec.getNameExpr(i) = v.getDeclaration()))
|
||||
)
|
||||
or
|
||||
result.(EvalCompoundAssignRhsInstruction).isAdditional(assgn, "compound-rhs")
|
||||
or
|
||||
result.(ExtractTupleElementInstruction).isAdditional(assgn, "extract:" + i.toString())
|
||||
}
|
||||
|
||||
@@ -735,9 +733,11 @@ module IR {
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the (implicit) right-hand side of a compound assignment.
|
||||
* An instruction that computes the (implicit) right-hand side of a compound assignment,
|
||||
* such as the `x + y` in `x += y`, and writes the resulting value to the assignment's
|
||||
* left-hand side.
|
||||
*/
|
||||
class EvalCompoundAssignRhsInstruction extends Instruction {
|
||||
class EvalCompoundAssignRhsInstruction extends WriteInstruction {
|
||||
CompoundAssignStmt assgn;
|
||||
|
||||
EvalCompoundAssignRhsInstruction() { this.isAdditional(assgn, "compound-rhs") }
|
||||
@@ -745,6 +745,8 @@ module IR {
|
||||
/** Gets the corresponding compound assignment statement. */
|
||||
CompoundAssignStmt getAssignment() { result = assgn }
|
||||
|
||||
override Instruction getRhs() { result = this }
|
||||
|
||||
override Type getResultType() { result = assgn.getRhs().getType() }
|
||||
|
||||
override ControlFlow::Root getRoot() { result.isRootOf(assgn) }
|
||||
@@ -1228,6 +1230,10 @@ module IR {
|
||||
or
|
||||
exists(IncDecStmt ids | write.isIn(ids) | lhs = ids.getOperand().stripParens())
|
||||
or
|
||||
exists(CompoundAssignStmt ca | write.isAdditional(ca, "compound-rhs") |
|
||||
lhs = ca.getLhs().stripParens()
|
||||
)
|
||||
or
|
||||
exists(FuncDef fd, int idx |
|
||||
write.isAdditional(fd.getBody(), "param-init:" + idx.toString()) and
|
||||
lhs = fd.getParameter(idx).getDeclaration()
|
||||
|
||||
@@ -1375,8 +1375,7 @@
|
||||
| exprs.go:51:3:51:5 | res | exprs.go:51:3:51:5 | After res |
|
||||
| exprs.go:51:3:51:14 | ... += ... | exprs.go:51:3:51:5 | Before res |
|
||||
| exprs.go:51:3:51:14 | After ... += ... | exprs.go:50:31:52:2 | After block statement |
|
||||
| exprs.go:51:3:51:14 | assign:0 ... += ... | exprs.go:51:3:51:14 | After ... += ... |
|
||||
| exprs.go:51:3:51:14 | compound-rhs ... += ... | exprs.go:51:3:51:14 | assign:0 ... += ... |
|
||||
| exprs.go:51:3:51:14 | compound-rhs ... += ... | exprs.go:51:3:51:14 | After ... += ... |
|
||||
| exprs.go:51:10:51:11 | After xs | exprs.go:51:13:51:13 | Before i |
|
||||
| exprs.go:51:10:51:11 | Before xs | exprs.go:51:10:51:11 | xs |
|
||||
| exprs.go:51:10:51:11 | xs | exprs.go:51:10:51:11 | After xs |
|
||||
@@ -2013,8 +2012,7 @@
|
||||
| main.go:17:3:17:3 | y | main.go:17:3:17:3 | After y |
|
||||
| main.go:17:3:17:9 | ... += ... | main.go:17:3:17:3 | Before y |
|
||||
| main.go:17:3:17:9 | After ... += ... | main.go:16:12:18:2 | After block statement |
|
||||
| main.go:17:3:17:9 | assign:0 ... += ... | main.go:17:3:17:9 | After ... += ... |
|
||||
| main.go:17:3:17:9 | compound-rhs ... += ... | main.go:17:3:17:9 | assign:0 ... += ... |
|
||||
| main.go:17:3:17:9 | compound-rhs ... += ... | main.go:17:3:17:9 | After ... += ... |
|
||||
| main.go:17:8:17:9 | 19 | main.go:17:8:17:9 | After 19 |
|
||||
| main.go:17:8:17:9 | After 19 | main.go:17:3:17:9 | compound-rhs ... += ... |
|
||||
| main.go:17:8:17:9 | Before 19 | main.go:17:8:17:9 | 19 |
|
||||
@@ -2131,8 +2129,7 @@
|
||||
| main.go:35:2:35:3 | star expression | main.go:35:2:35:3 | After star expression |
|
||||
| main.go:35:2:35:9 | ... += ... | main.go:35:2:35:3 | Before star expression |
|
||||
| main.go:35:2:35:9 | After ... += ... | main.go:34:19:36:1 | After block statement |
|
||||
| main.go:35:2:35:9 | assign:0 ... += ... | main.go:35:2:35:9 | After ... += ... |
|
||||
| main.go:35:2:35:9 | compound-rhs ... += ... | main.go:35:2:35:9 | assign:0 ... += ... |
|
||||
| main.go:35:2:35:9 | compound-rhs ... += ... | main.go:35:2:35:9 | After ... += ... |
|
||||
| main.go:35:3:35:3 | After x | main.go:35:2:35:3 | star expression |
|
||||
| main.go:35:3:35:3 | Before x | main.go:35:3:35:3 | x |
|
||||
| main.go:35:3:35:3 | x | main.go:35:3:35:3 | After x |
|
||||
@@ -2968,8 +2965,7 @@
|
||||
| stmts5.go:8:2:8:7 | selection of val | stmts5.go:8:2:8:7 | After selection of val |
|
||||
| stmts5.go:8:2:8:16 | ... += ... | stmts5.go:8:2:8:7 | Before selection of val |
|
||||
| stmts5.go:8:2:8:16 | After ... += ... | stmts5.go:7:33:9:1 | After block statement |
|
||||
| stmts5.go:8:2:8:16 | assign:0 ... += ... | stmts5.go:8:2:8:16 | After ... += ... |
|
||||
| stmts5.go:8:2:8:16 | compound-rhs ... += ... | stmts5.go:8:2:8:16 | assign:0 ... += ... |
|
||||
| stmts5.go:8:2:8:16 | compound-rhs ... += ... | stmts5.go:8:2:8:16 | After ... += ... |
|
||||
| stmts5.go:8:12:8:16 | After other | stmts5.go:8:2:8:16 | compound-rhs ... += ... |
|
||||
| stmts5.go:8:12:8:16 | Before other | stmts5.go:8:12:8:16 | other |
|
||||
| stmts5.go:8:12:8:16 | other | stmts5.go:8:12:8:16 | After other |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
| 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 |
|
||||
| main.go:14:2:14:8 | assign:0 ... := ... | main.go:14:2:14:2 | y | main.go:14:7:14:8 | 23 |
|
||||
| main.go:17:3:17:9 | assign:0 ... += ... | main.go:14:2:14:2 | y | main.go:17:3:17:9 | compound-rhs ... += ... |
|
||||
| main.go:17:3:17:9 | compound-rhs ... += ... | main.go:14:2:14:2 | y | main.go:17:3:17:9 | compound-rhs ... += ... |
|
||||
| main.go:21:3:21:7 | assign:0 ... = ... | main.go:13:6:13:6 | x | main.go:21:7:21:7 | y |
|
||||
| main.go:26:28:32:1 | param-init:0 block statement | main.go:26:10:26:10 | x | main.go:26:28:32:1 | arg:0 block statement |
|
||||
| main.go:27:2:27:13 | assign:0 ... := ... | main.go:27:2:27:2 | a | main.go:27:10:27:10 | x |
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
| testdata.go:134:3:134:17 | assign:0 ... = ... | This definition of x is never used. |
|
||||
| testdata.go:143:3:143:17 | assign:0 ... = ... | This definition of x is never used. |
|
||||
| testdata.go:164:3:164:17 | assign:0 ... = ... | This definition of x is never used. |
|
||||
| testdata.go:172:3:172:18 | assign:0 ... += ... | This definition of x is never used. |
|
||||
| testdata.go:172:3:172:18 | compound-rhs ... += ... | This definition of x is never used. |
|
||||
| testdata.go:180:3:180:5 | increment statement | This definition of x is never used. |
|
||||
| testdata.go:201:2:201:24 | assign:0 ... = ... | This definition of x is never used. |
|
||||
| testdata.go:262:2:262:16 | assign:0 ... = ... | This definition of x is never used. |
|
||||
| testdata.go:268:2:268:16 | assign:0 ... = ... | This definition of x is never used. |
|
||||
| testdata.go:309:2:309:7 | assign:0 ... /= ... | This definition of a is never used. |
|
||||
| testdata.go:321:2:321:7 | assign:0 ... %= ... | This definition of a is never used. |
|
||||
| testdata.go:309:2:309:7 | compound-rhs ... /= ... | This definition of a is never used. |
|
||||
| testdata.go:321:2:321:7 | compound-rhs ... %= ... | This definition of a is never used. |
|
||||
| testdata.go:387:3:387:17 | assign:0 ... = ... | This definition of x is never used. |
|
||||
| testdata.go:432:3:432:17 | assign:0 ... = ... | This definition of x is never used. |
|
||||
| testdata.go:434:3:434:17 | assign:0 ... = ... | This definition of x is never used. |
|
||||
|
||||
Reference in New Issue
Block a user