Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

addgetEnclosingBlock for Go#21089

Lslightly started this conversation inGeneral
Jan 4, 2026· 2 comments· 4 replies
Discussion options

/** Gets the parent node of this AST node, but without crossing function boundaries. */
privateAstNodeparentInSameFunction(){
result=this.getParent()and
notthisinstanceofFuncDef
}
/** Gets the innermost function definition to which this AST node belongs, if any. */
pragma[nomagic]
FuncDefgetEnclosingFunction(){result=this.getParent().parentInSameFunction*()}

In rust and cpp,getEnclosingBlock is supported as shown bysearch result. Would Go support this?

/** Gets the parent node of this AST node, but without crossing block boundaries. */privateAstNodeparentInSameBlock(){result=this.getParent()andnotthisinstanceofBlockStmt}/** Gets the innermost block statement to which this AST node belongs, if any. */pragma[nomagic]BlockStmtgetEnclosingBlock(){result=this.getParent().parentInSameBlock*()}
You must be logged in to vote

Replies: 2 comments 4 replies

Comment options

Can I ask what you want to use it for?

The two examples you give are very much about syntactic blocks. Both of those languages have aBlockExpr orBlockStmt in their AST, which we don't have in the Go AST. We have something a bit similar in go:getEnclosingBlock onControlFlow::Node, which returns aBasicBlock. But it uses the control flow graph, so it goes beyond the AST level to what is actually happening semantically. To see the difference, consider this function:

funcf() {g()h()}

At a syntactic level it clearly has one block. But from the point of the view of control flow it has two basic blocks, becauseg might panic, in which caseh would not be called after it.

You must be logged in to vote
4 replies
@Lslightly
Comment options

Usage Scenario: decide whether the declaration ofobj is in the sameBlockStmt asGoStmt and assert thatobj will not be accessed afterGoStmt in execution(or semantically).

varobjSgofunc() {access(obj) }()

If they are not in sameBlockStmt, then usuallyobj is declared in outerBlockStmt.

varobjSfor {gofunc() {access(obj) }()}

Both of those languages have a BlockExpr or BlockStmt in their AST, which we don't have in the Go AST

go-all package(4.2.5 version) in codeql v2.21.3 codeql qlpacks haveBlockStmt. I also checked thelatest codeql packs.BlockStmt exists. What do you mean by "which we don't have in the Go AST"?

We have something a bit similar in go:getEnclosingBlock onControlFlow::Node

Thanks for your explanation! In the second example above, using AST levelgetEnclosingBlock to decide thatobj might be used in later iteration is fast and simple, because I can easily get theGoStmt which referencesobj. Theobj is categorized asclass MovedToHeapVar extends LocalVariable byLocation, which is provided by external predicates.

I will try to connectControlFlow::Node withGoStmt and declarationIdent and usegetASuccessor to assert thatobj will not be accessed afterGoStmt. But I doubt that it can be complex.

@owen-mc
Comment options

You're right, I missedBlockStmt in the codeql go library because I only searched inAST.qll. My apologies.

Thank you for explaining your use case. I have made a PR to add this as a member predicate:#21254 .

In the meantime, you can write the code that you want in a top-level predicate rather than a member predicate:

  /** Gets the innermost block statement to which this AST node belongs, if any. */  BlockStmt getEnclosingBlock(AstNode an) {    exists(AstNode p | p = an.getParent() |      result = p      or      not p instanceof BlockStmt and      result = p.getEnclosingBlock()    )  }

I should also mention theScope class, which unfortunately isn't very useful in this case. We can only really talk about scopes ofEntitys, like a variable, but I don't think we can get aScope corresponding to agoStmt.

@owen-mc
Comment options

To be more specific, if you look at the results ofLocalScope.getNode() you will see which AST nodes can introduce a new (local) scope. For example, you can define a new variable before the condition of an if statement and it will be in scope for the rest of the if statement. See also the QLDoc comment forScopeNode for more examples. (For your use case you are probably only interested in a subset of scopes in which aGoStmt can appear, which may just be those created byBlockStmts.)

@Lslightly
Comment options

Thanks for your explanation aboutScope andLocalScope. Actually, the way I try first to match the declaration block of variable and the blockGoStmt resides in is comparingLocalScope.getNode() of variable, the declaration "block"(but actually it isFuncTypeExpr, notBlockStmt), and enclosingBlockStmt ofGoStmt. I failed becauseFuncTypeExpr could not be equal toBlockStmt.

Then I turn to find the enclosingBlockStmt of variable declaration. So the same pattern ofgetEnclosingBlock appears twice and I'm here with the proposal.

Comment options

#21254 has been merged, so this should be in release v2.24.2, which should be out in about two weeks.

You must be logged in to vote
0 replies
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Category
General
Labels
None yet
2 participants
@Lslightly@owen-mc

[8]ページ先頭

©2009-2026 Movatter.jp