Skip to content

Commit

Permalink
go/ir: don't treat _ specially in Prog.{Func,Const,Var}Value
Browse files Browse the repository at this point in the history
Because of a (long-since fixed) bug in go/types, the Program
accessors that accept types.Objects didn't work for blank-named
objects. This created an edge case that needed to be skipped
in client code: FuncValue("_") would return nil, for example,
even thought there's no reason clients shouldn't be able to
analyze the bodies of blank functions.

This change inserts all objects, regardless of name, into the
Package.objects map to eliminate this edge case. (Of course,
declarations must still have non-blank names to appear in the
Members mapping.)

(cherry picked from commit 942d9acc1ecb8b0ec51d6660adb17ee80ec47090 in
x/tools)

Co-authored-by: Dominik Honnef <dominik@honnef.co>
  • Loading branch information
adonovan and dominikh committed May 20, 2024
1 parent 8877e44 commit d074ce0
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 20 deletions.
34 changes: 16 additions & 18 deletions go/ir/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,11 @@ func memberFromObject(pkg *Package, obj types.Object, syntax ast.Node, goversion
}

case *types.TypeName:
pkg.Members[name] = &Type{
object: obj,
pkg: pkg,
if name != "_" {
pkg.Members[name] = &Type{
object: obj,
pkg: pkg,
}
}

case *types.Const:
Expand All @@ -70,7 +72,9 @@ func memberFromObject(pkg *Package, obj types.Object, syntax ast.Node, goversion
pkg: pkg,
}
pkg.values[obj] = c.Value
pkg.Members[name] = c
if name != "_" {
pkg.Members[name] = c
}

case *types.Var:
g := &Global{
Expand All @@ -80,7 +84,9 @@ func memberFromObject(pkg *Package, obj types.Object, syntax ast.Node, goversion
typ: types.NewPointer(obj.Type()), // address
}
pkg.values[obj] = g
pkg.Members[name] = g
if name != "_" {
pkg.Members[name] = g
}

case *types.Func:
sig := obj.Type().(*types.Signature)
Expand Down Expand Up @@ -114,7 +120,7 @@ func memberFromObject(pkg *Package, obj types.Object, syntax ast.Node, goversion

pkg.values[obj] = fn
pkg.Functions = append(pkg.Functions, fn)
if sig.Recv() == nil {
if name != "_" && sig.Recv() == nil {
pkg.Members[name] = fn // package-level function
}

Expand All @@ -133,9 +139,7 @@ func membersFromDecl(pkg *Package, decl ast.Decl, goversion string) {
case token.CONST:
for _, spec := range decl.Specs {
for _, id := range spec.(*ast.ValueSpec).Names {
if !isBlankIdent(id) {
memberFromObject(pkg, pkg.info.Defs[id], nil, "")
}
memberFromObject(pkg, pkg.info.Defs[id], nil, "")
}
}

Expand All @@ -145,26 +149,20 @@ func membersFromDecl(pkg *Package, decl ast.Decl, goversion string) {
pkg.initVersion[rhs] = goversion
}
for _, id := range spec.(*ast.ValueSpec).Names {
if !isBlankIdent(id) {
memberFromObject(pkg, pkg.info.Defs[id], spec, goversion)
}
memberFromObject(pkg, pkg.info.Defs[id], spec, goversion)
}
}

case token.TYPE:
for _, spec := range decl.Specs {
id := spec.(*ast.TypeSpec).Name
if !isBlankIdent(id) {
memberFromObject(pkg, pkg.info.Defs[id], nil, "")
}
memberFromObject(pkg, pkg.info.Defs[id], nil, "")
}
}

case *ast.FuncDecl:
id := decl.Name
if !isBlankIdent(id) {
memberFromObject(pkg, pkg.info.Defs[id], decl, goversion)
}
memberFromObject(pkg, pkg.info.Defs[id], decl, goversion)
}
}

Expand Down
2 changes: 1 addition & 1 deletion internal/passes/buildir/buildir.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ var Analyzer = &analysis.Analyzer{
}

// IR provides intermediate representation for all the
// non-blank source functions in the current package.
// source functions in the current package.
type IR struct {
Pkg *ir.Package
SrcFuncs []*ir.Function
Expand Down
2 changes: 1 addition & 1 deletion internal/passes/buildir/buildir_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func Test(t *testing.T) {

irinfo := result.(*buildir.IR)
got := fmt.Sprint(irinfo.SrcFuncs)
want := `[a.init a.Fib (a.T).fib]`
want := `[a.init a.Fib (a.T).fib a._ a._]`
if got != want {
t.Errorf("IR.SrcFuncs = %s, want %s", got, want)
for _, f := range irinfo.SrcFuncs {
Expand Down
4 changes: 4 additions & 0 deletions internal/passes/buildir/testdata/src/a/a.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ func (T) fib(x int) int { return Fib(x) }
func _() {
print("hi")
}

func _() {
print("hi")
}

0 comments on commit d074ce0

Please sign in to comment.