Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/tools/go/analysis/passes/ctrlflow: encode more knowledge about standard library in ctrlflow analyzer #497

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion go/analysis/passes/ctrlflow/ctrlflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,21 @@ func (c *CFGs) callMayReturn(call *ast.CallExpr) (r bool) {
return false // panic never returns
}

// "Some driver implementations (such as those based on Bazel and Blaze) do not
// currently apply analyzers to packages of the standard library. Therefore, for
// best results, analyzer authors should not rely on analysis facts being available
// for standard packages." [1].
// This means that we cannot rely on the noReturn fact being available for standard
// library functions.
// Therefore, here we check if the function is an intrinsic no-return function.
//
// [1]: https://pkg.go.dev/golang.org/x/tools/go/analysis
if sel, ok := call.Fun.(*ast.SelectorExpr); ok {
if fn, ok := c.pass.TypesInfo.ObjectOf(sel.Sel).(*types.Func); ok && isIntrinsicNoReturn(fn) {
return false // intrinsic no-return functions
}
}

// Is this a static call? Also includes static functions
// parameterized by a type. Such functions may or may not
// return depending on the parameter type, but in some
Expand Down Expand Up @@ -227,5 +242,12 @@ func isIntrinsicNoReturn(fn *types.Func) bool {
// Add functions here as the need arises, but don't allocate memory.
path, name := fn.Pkg().Path(), fn.Name()
return path == "syscall" && (name == "Exit" || name == "ExitProcess" || name == "ExitThread") ||
path == "runtime" && name == "Goexit"
(path == "runtime" && name == "Goexit") ||
// Ideally we should not need to list the following functions since they
// internally call the functions above. However, we will only know that _if_
// we also analyze the standard library. For some driver implementations like
// Bazel it would not do so currently. Therefore, we list them here.
(path == "log" && (name == "Fatal" || name == "Fatalf")) ||
(path == "os" && (name == "Exit")) ||
(path == "testing" && (name == "FailNow" || name == "Skip" || name == "Skipf" || name == "SkipNow"))
}