From 9aa950c40789223d9e8df7d1ec657cd313e6c7aa Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 5 Jan 2021 03:28:06 -0800 Subject: [PATCH] [dev.regabi] cmd/compile: make ir.OuterValue safer For OINDEX expressions, ir.OuterValue depends on knowing the indexee's type. Rather than silently acting as though it's not an array, make it loudly fail. The only code that needs to be fixed to support this is checkassign during typechecking, which needs to avoid calling ir.OuterValue now if typechecking the assigned operand already failed. Passes toolstash -cmp. Change-Id: I935cae0dacc837202bc6b63164dc2f0a6fde005c Reviewed-on: https://go-review.googlesource.com/c/go/+/281539 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/ir/node.go | 5 ++++- src/cmd/compile/internal/typecheck/typecheck.go | 13 ++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index a5a7203faa..850d7343aa 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -568,7 +568,10 @@ func OuterValue(n Node) Node { continue case OINDEX: nn := nn.(*IndexExpr) - if nn.X.Type() != nil && nn.X.Type().IsArray() { + if nn.X.Type() == nil { + base.Fatalf("OuterValue needs type for %v", nn.X) + } + if nn.X.Type().IsArray() { n = nn.X continue } diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index 981f4ef1d6..c3a5a3c40f 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -1612,6 +1612,14 @@ func checklvalue(n ir.Node, verb string) { } func checkassign(stmt ir.Node, n ir.Node) { + // have already complained about n being invalid + if n.Type() == nil { + if base.Errors() == 0 { + base.Fatalf("expected an error about %v", n) + } + return + } + // Variables declared in ORANGE are assigned on every iteration. if !ir.DeclaredBy(n, stmt) || stmt.Op() == ir.ORANGE { r := ir.OuterValue(n) @@ -1633,11 +1641,6 @@ func checkassign(stmt ir.Node, n ir.Node) { return } - // have already complained about n being invalid - if n.Type() == nil { - return - } - switch { case n.Op() == ir.ODOT && n.(*ir.SelectorExpr).X.Op() == ir.OINDEXMAP: base.Errorf("cannot assign to struct field %v in map", n)