Skip to content

Commit 1a8d240

Browse files
committed
Remove/reduce comments
1 parent c80dd0e commit 1a8d240

2 files changed

Lines changed: 26 additions & 71 deletions

File tree

go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll

Lines changed: 24 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,8 @@ module CfgImpl {
8282
or
8383
e.getParent*() = any(Go::ArrayTypeExpr ate).getLength()
8484
or
85-
// The body block of a switch (expression or type) is transparent: the
86-
// shared switch model wires control flow directly from the switch to its
87-
// case clauses (in control-flow order) and between cases, so the
85+
// The shared switch model wires control flow directly from the switch to
86+
// its case clauses (in control-flow order) and between cases, so the
8887
// enclosing block must not introduce its own nodes or default
8988
// left-to-right sequencing of the case clauses.
9089
e = any(Go::SwitchStmt sw).getBody()
@@ -217,12 +216,6 @@ module CfgImpl {
217216
}
218217

219218
class ForeachStmt extends LoopStmt instanceof Go::RangeStmt {
220-
// Go's `range` statement binds its key and value by destructuring the
221-
// current element. The extractor synthesizes a single "range element"
222-
// node grouping the key and value (see `Go::RangeElementExpr`), which we
223-
// present here as the loop variable. The shared library routes control
224-
// flow into and out of this node, and Go wires the destructuring through
225-
// it (see `rangeStmtStep`).
226219
Expr getVariable() { result = this.(Go::RangeStmt).getPattern() }
227220

228221
Expr getCollection() { result = this.(Go::RangeStmt).getDomain() }
@@ -298,18 +291,11 @@ module CfgImpl {
298291
DefaultCase() { not exists(this.(Go::CaseClause).getAnExpr()) }
299292
}
300293

301-
/** Gets the initializer of `switch` statement `switch`, if any. */
302294
AstNode getSwitchInit(Switch switch) { result = switch.(Go::SwitchStmt).getInit() }
303295

304-
/**
305-
* Go has no implicit fall-through between case clauses; a case that runs to
306-
* the end of its body breaks out of the switch. Fall-through only happens
307-
* when the case body ends with an explicit `fallthrough` statement, in
308-
* which case control transfers to the next case clause's body (in source
309-
* order). The shared library models this by chaining the body of such a
310-
* case to the body of the following case.
311-
*/
312296
predicate fallsThrough(Case c) {
297+
// Go has no implicit fall-through between case clauses; an explicit
298+
// `fallthrough` statement is required.
313299
c.(Go::CaseClause).getStmt(max(int i | exists(c.(Go::CaseClause).getStmt(i)))) instanceof
314300
Go::FallthroughStmt
315301
}
@@ -444,11 +430,11 @@ module CfgImpl {
444430

445431
predicate preOrderExpr(Ast::Expr e) {
446432
// The call of a `defer` statement is not invoked at the statement
447-
// itself; its callee and arguments are evaluated in place, but the call
448-
// is only invoked later, at function exit (modelled by the `defer-invoke`
449-
// node and `additionalSuccessor`). Marking it as pre-order means no in-order
450-
// "invocation" node (and hence no inline exceptional-exit edge) is
451-
// created at the `defer` statement.
433+
// itself; its callee expression and arguments are evaluated in place,
434+
// but the call is only invoked later, at function exit (modelled by the
435+
// `defer-invoke` node and `additionalSuccessor`). Marking it as
436+
// pre-order means no in-order "invocation" node (and hence no inline
437+
// exceptional-exit edge) is created at the `defer` statement.
452438
e = any(Go::DeferStmt s).getCall()
453439
or
454440
// Parenthesized expressions are value-transparent (via `propagatesValue`)
@@ -963,12 +949,12 @@ module CfgImpl {
963949
exists(Go::FuncDef fd | funcHasDefer(fd) |
964950
successorType instanceof DirectSuccessor and
965951
(
966-
// (a) an exit predecessor with no active defer flows straight to the exit target
952+
// an exit predecessor with no active defer flows straight to the exit target
967953
normalExitPred(n1, fd) and
968954
n1 = reachableBeforeNextDeferRegistration(funcEntry(fd)) and
969955
deferChainExitTarget(fd, n2)
970956
or
971-
// (b) an exit predecessor flows to the invocation of the last-registered active defer
957+
// an exit predecessor flows to the invocation of the last-registered active defer
972958
exists(Go::DeferStmt d, PreControlFlowNode reg |
973959
deferRegistration(reg, d) and
974960
d.getEnclosingFunction() = fd and
@@ -977,7 +963,7 @@ module CfgImpl {
977963
deferInvoke(n2, d)
978964
)
979965
or
980-
// (c) deferred invocations chain in last-in-first-out order
966+
// deferred invocations chain in last-in-first-out order
981967
exists(Go::DeferStmt laterRegistered, Go::DeferStmt earlierRegistered |
982968
laterRegistered.getEnclosingFunction() = fd and
983969
nextRegisteredDefer(laterRegistered, earlierRegistered) and
@@ -986,7 +972,7 @@ module CfgImpl {
986972
deferInvoke(n2, earlierRegistered)
987973
)
988974
or
989-
// (d) the invocation of the first-registered (last to run) defer flows to the exit target
975+
// the invocation of the first-registered (last to run) defer flows to the exit target
990976
exists(Go::DeferStmt firstD |
991977
firstRegisteredDefer(firstD, fd) and
992978
deferInvocationMayReturnNormally(firstD) and
@@ -995,7 +981,7 @@ module CfgImpl {
995981
)
996982
)
997983
or
998-
// (e) a possible panic with active defers flows to the last-registered active defer
984+
// a possible panic with active defers flows to the last-registered active defer
999985
successorType instanceof ExceptionSuccessor and
1000986
exists(Go::DeferStmt d, PreControlFlowNode reg |
1001987
deferRegistration(reg, d) and
@@ -1113,7 +1099,6 @@ module CfgImpl {
11131099
|
11141100
epilogueStep(assgn, n1, n2)
11151101
or
1116-
// Last epilogue -> after the assignment
11171102
n1.isAdditional(assgn, getLastEpilogueTag(assgn)) and
11181103
n2.isAfter(assgn)
11191104
)
@@ -1210,7 +1195,6 @@ module CfgImpl {
12101195
exists(Go::ReturnStmt ret |
12111196
epilogueStep(ret, n1, n2)
12121197
or
1213-
// Last return epilogue -> return node
12141198
n1.isAdditional(ret, getLastEpilogueTag(ret)) and
12151199
n2.isIn(ret)
12161200
)
@@ -1236,10 +1220,8 @@ module CfgImpl {
12361220
|
12371221
epilogueStep(call, n1, n2)
12381222
or
1239-
// Last tuple-extraction node -> the call's invocation node
12401223
n1.isAdditional(call, getLastEpilogueTag(call)) and n2.isIn(call)
12411224
or
1242-
// Invocation node -> after the call (unless the call never returns normally)
12431225
n1.isIn(call) and
12441226
n2.isAfter(call) and
12451227
not beginAbruptCompletion(call, n1, _, true)
@@ -1308,7 +1290,6 @@ module CfgImpl {
13081290
exists(Go::SliceExpr se |
13091291
n1.isBefore(se) and n2.isBefore(se.getBase())
13101292
or
1311-
// After base -> implicit deref, or (if none) the first present bound / slice eval
13121293
n1.isAfter(se.getBase()) and
13131294
(
13141295
if implicitDerefCondition(se.getBase())
@@ -1318,7 +1299,6 @@ module CfgImpl {
13181299
or
13191300
n1.isAdditional(se.getBase(), "implicit-deref") and sliceNext(se, -1, n2)
13201301
or
1321-
// After a present bound -> the next present bound / slice eval
13221302
n1.isAfter(se.getLow()) and sliceNext(se, 0, n2)
13231303
or
13241304
n1.isAfter(se.getHigh()) and sliceNext(se, 1, n2)
@@ -1344,7 +1324,6 @@ module CfgImpl {
13441324
(
13451325
n1.isBefore(sel) and n2.isBefore(sel.getBase())
13461326
or
1347-
// After base (no implicit-deref) -> first implicit-field or In(sel)
13481327
n1.isAfter(sel.getBase()) and
13491328
not implicitDerefCondition(sel.getBase()) and
13501329
(
@@ -1358,23 +1337,22 @@ module CfgImpl {
13581337
not implicitFieldSelection(sel, _, _) and n2.isIn(sel)
13591338
)
13601339
or
1361-
// After base (has implicit-deref) -> implicit-deref node
13621340
n1.isAfter(sel.getBase()) and
13631341
implicitDerefCondition(sel.getBase()) and
13641342
n2.isAdditional(sel.getBase(), "implicit-deref")
13651343
or
1366-
// After implicit-deref -> first implicit-field or In(sel)
13671344
n1.isAdditional(sel.getBase(), "implicit-deref") and
13681345
(
1346+
// Has implicit field reads: go to outermost (highest index)
13691347
exists(int maxIdx |
13701348
maxIdx = max(int i | implicitFieldSelection(sel, i, _)) and
13711349
n2.isAdditional(sel, "implicit-field:" + maxIdx.toString())
13721350
)
13731351
or
1352+
// No implicit field reads: go directly to In(sel)
13741353
not implicitFieldSelection(sel, _, _) and n2.isIn(sel)
13751354
)
13761355
or
1377-
// Between implicit field reads: descend from index i to i-1
13781356
exists(int i |
13791357
i > 1 and
13801358
implicitFieldSelection(sel, i, _) and
@@ -1383,7 +1361,6 @@ module CfgImpl {
13831361
n2.isAdditional(sel, "implicit-field:" + (i - 1).toString())
13841362
)
13851363
or
1386-
// Last implicit field read (index 1) -> In(sel)
13871364
implicitFieldSelection(sel, 1, _) and
13881365
n1.isAdditional(sel, "implicit-field:1") and
13891366
n2.isIn(sel)
@@ -1400,18 +1377,15 @@ module CfgImpl {
14001377
*/
14011378
private predicate compositeLitStep(PreControlFlowNode n1, PreControlFlowNode n2) {
14021379
exists(Go::CompositeLit lit |
1403-
// Before -> In (the literal allocation)
14041380
n1.isBefore(lit) and n2.isIn(lit)
14051381
or
1406-
// In -> first element, or After if no elements
14071382
n1.isIn(lit) and
14081383
(
14091384
n2.isBefore(lit.getElement(0))
14101385
or
14111386
not exists(lit.getElement(_)) and n2.isAfter(lit)
14121387
)
14131388
or
1414-
// After element -> lit-init -> next element or After.
14151389
// Positional array/slice elements have an implicit index that is
14161390
// modelled on the `lit-init` instruction itself (see
14171391
// `IR::InitLiteralElementInstruction`) rather than as a separate node.
@@ -1607,17 +1581,6 @@ module CfgImpl {
16071581
)
16081582
}
16091583

1610-
/**
1611-
* Function definition prologue and epilogue:
1612-
* - Prologue: parameters are modelled as native CFG nodes by the shared
1613-
* library (Entry -> param -> ... -> Before(body)). The remaining
1614-
* prologue on Before(body) zero-initializes any named result
1615-
* variables: zero-init:0 -> zero-init:1 -> ... -> first statement.
1616-
* - Epilogue: return -> result-read:0 -> result-read:1 -> ... -> result-read:last
1617-
*
1618-
* The last result-read node goes to `After(body)`, from which the shared
1619-
* callable CFG continues to the normal exit.
1620-
*/
16211584
private predicate hasFuncDefPrologue(Go::FuncDef fd) { exists(fd.getResultVar(_)) }
16221585

16231586
private predicate funcDefBodyStart(Go::FuncDef fd, PreControlFlowNode n) {
@@ -1627,47 +1590,41 @@ module CfgImpl {
16271590
n.isAdditional(fd.getBody(), "result-read:0")
16281591
}
16291592

1593+
/**
1594+
* Function body flow for named result variables: `Before(body)` ->
1595+
* `zero-init:0` -> ... -> first statement -> ... -> `result-read:0` -> ...
1596+
* -> `After(body)`. Parameters precede `Before(body)` through the shared
1597+
* callable flow. Return and defer handling route into the result-read
1598+
* sequence separately; this predicate sequences its nodes and routes
1599+
* defer-free fall-through into it.
1600+
*/
16301601
private predicate funcDefStep(PreControlFlowNode n1, PreControlFlowNode n2) {
16311602
exists(Go::FuncDef fd | exists(fd.getBody()) |
1632-
// Before(body) -> first result-var zero-init node. Parameters are
1633-
// modelled as native CFG nodes by the shared library and route
1634-
// Entry -> param -> ... -> Before(body) ahead of this point; the
1635-
// no-result-variable case (Before(body) -> first statement) is handled
1636-
// by the shared library's default control flow.
16371603
n1.isBefore(fd.getBody()) and
16381604
exists(fd.getResultVar(0)) and
16391605
n2.isAdditional(fd.getBody(), "zero-init:0")
16401606
or
1641-
// zero-init:j -> next: zero-init:(j+1), or Before(body).
1642-
// The zero-init node also writes the result variable (see
1643-
// `IR::EvalImplicitInitInstruction`), so there is no separate result-init node.
16441607
exists(int j | exists(fd.getResultVar(j)) |
16451608
n1.isAdditional(fd.getBody(), "zero-init:" + j.toString()) and
16461609
(
1647-
// Next result var exists
16481610
exists(fd.getResultVar(j + 1)) and
16491611
n2.isAdditional(fd.getBody(), "zero-init:" + (j + 1).toString())
16501612
or
1651-
// No next result var: go to Before(body)
16521613
not exists(fd.getResultVar(j + 1)) and
16531614
funcDefBodyStart(fd, n2)
16541615
)
16551616
)
16561617
or
1657-
// result-read:j -> result-read:(j+1)
16581618
exists(int j | exists(fd.getResultVar(j + 1)) |
16591619
n1.isAdditional(fd.getBody(), "result-read:" + j.toString()) and
16601620
n2.isAdditional(fd.getBody(), "result-read:" + (j + 1).toString())
16611621
)
16621622
or
1663-
// Normal fall-through enters the result-read epilogue when there are
1664-
// named results but no deferred calls.
16651623
not funcHasDefer(fd) and
16661624
exists(fd.getResultVar(0)) and
16671625
n1.isAfter(getLastRankedChild(fd.getBody())) and
16681626
n2.isAdditional(fd.getBody(), "result-read:0")
16691627
or
1670-
// The completed result-read epilogue reaches `After(body)`.
16711628
exists(int j |
16721629
exists(fd.getResultVar(j)) and
16731630
not exists(fd.getResultVar(j + 1)) and

shared/controlflow/codeql/controlflow/ControlFlowGraph.qll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -684,10 +684,8 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
684684
not postOrInOrder(n) and
685685
not additionalNode(n, _, _) and
686686
not inConditionalContext(n, _) and
687-
// A switch is a branching construct with an explicit step from its
688-
// "before" node to its "after" node, so it must keep distinct before and
689-
// after nodes even when it has no children (e.g. an empty `switch {}`).
690-
// Merging them would otherwise turn that step into a spurious self-loop.
687+
// An empty switch statement still needs distinct before and after nodes
688+
// to avoid a spurious self-loop.
691689
not n instanceof Switch
692690
}
693691

0 commit comments

Comments
 (0)