Fix calls for defer statements

This commit is contained in:
Owen Mansel-Chan
2026-06-16 19:26:27 +01:00
parent 13bf978f64
commit 138a1c3c99
2 changed files with 14 additions and 1 deletions

View File

@@ -354,7 +354,15 @@ module GoCfg {
)
}
predicate preOrderExpr(Ast::Expr e) { none() }
predicate preOrderExpr(Ast::Expr e) {
// The call of a `defer` statement is not invoked at the statement
// itself; its callee and arguments are evaluated in place, but the call
// is only invoked later, at function exit (modelled by the `defer-invoke`
// node and `deferExitStep`). Marking it as pre-order means no in-order
// "invocation" node (and hence no inline exceptional-exit edge) is
// created at the `defer` statement.
e = any(Go::DeferStmt s).getCall()
}
predicate propagatesValue(Ast::AstNode child, Ast::AstNode parent) {
child = parent.(Go::ParenExpr).getExpr()

View File

@@ -218,6 +218,11 @@ module IR {
EvalInstruction() {
this.isIn(e)
or
// The call of a `defer` statement is pre-order (it has no in-order
// "invocation" node at the statement), so its value is produced by the
// `defer-invoke` node that models the call at function exit.
this.isAdditional(e, "defer-invoke")
or
// `NotExpr` and `LogicalBinaryExpr` are not in `postOrInOrder`, so they
// don't have an `isIn` node. Only use the after-node when the
// expression is not in a conditional context; otherwise the value is