mirror of
https://github.com/golang/go
synced 2024-11-02 11:50:30 +00:00
cmd/compile: allow composite literal structs with _ fields
Given code such as type T struct { _ string } func f() { var x = T{"space"} // ... } the compiler rewrote the 'var x' line as var x T x._ = "space" The compiler then rejected the assignment to a blank field, thus rejecting valid code. It also failed to catch a number of invalid assignments. And there were insufficient checks for validity when emitting static data, leading to ICEs. To fix, check earlier for explicit blanks field names, explicitly handle legit blanks in sinit, and don't try to emit static data for nodes for which typechecking has failed. Fixes #19482 Change-Id: I594476171d15e6e8ecc6a1749e3859157fe2c929 Reviewed-on: https://go-review.googlesource.com/38006 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
44a0681ae4
commit
c9446398e8
4 changed files with 44 additions and 3 deletions
|
@ -725,6 +725,9 @@ func fixedlit(ctxt initContext, kind initKind, n *Node, var_ *Node, init *Nodes)
|
|||
if r.Op != OSTRUCTKEY {
|
||||
Fatalf("fixedlit: rhs not OSTRUCTKEY: %v", r)
|
||||
}
|
||||
if isblanksym(r.Sym) {
|
||||
return nblank, r.Left
|
||||
}
|
||||
return nodSym(ODOT, var_, r.Sym), r.Left
|
||||
}
|
||||
default:
|
||||
|
@ -1346,8 +1349,12 @@ func isvaluelit(n *Node) bool {
|
|||
}
|
||||
|
||||
func genAsStatic(as *Node) {
|
||||
if as.Left.Type == nil {
|
||||
Fatalf("genAsStatic as.Left not typechecked")
|
||||
}
|
||||
|
||||
var nam Node
|
||||
if !stataddr(&nam, as.Left) || nam.Class != PEXTERN {
|
||||
if !stataddr(&nam, as.Left) || (nam.Class != PEXTERN && as.Left != nblank) {
|
||||
Fatalf("genAsStatic: lhs %v", as.Left)
|
||||
}
|
||||
|
||||
|
|
|
@ -3100,7 +3100,7 @@ func typecheckcomplit(n *Node) *Node {
|
|||
// the field to the right of the dot,
|
||||
// so s will be non-nil, but an OXDOT
|
||||
// is never a valid struct literal key.
|
||||
if key.Sym == nil || key.Op == OXDOT {
|
||||
if key.Sym == nil || key.Op == OXDOT || isblanksym(key.Sym) {
|
||||
yyerror("invalid field name %v in struct initializer", key)
|
||||
l.Left = typecheck(l.Left, Erv)
|
||||
continue
|
||||
|
|
|
@ -70,7 +70,7 @@ func (s *LSym) GrowCap(c int64) {
|
|||
// prepwrite prepares to write data of size siz into s at offset off.
|
||||
func (s *LSym) prepwrite(ctxt *Link, off int64, siz int) {
|
||||
if off < 0 || siz < 0 || off >= 1<<30 {
|
||||
log.Fatalf("prepwrite: bad off=%d siz=%d s=%v", off, siz, s)
|
||||
ctxt.Diag("prepwrite: bad off=%d siz=%d s=%v", off, siz, s)
|
||||
}
|
||||
if s.Type == SBSS || s.Type == STLSBSS {
|
||||
ctxt.Diag("cannot supply data for BSS var")
|
||||
|
|
34
test/fixedbugs/issue19482.go
Normal file
34
test/fixedbugs/issue19482.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
// errorcheck
|
||||
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Compiler rejected initialization of structs to composite literals
|
||||
// in a non-static setting (e.g. in a function)
|
||||
// when the struct contained a field named _.
|
||||
|
||||
package p
|
||||
|
||||
type T struct {
|
||||
_ string
|
||||
}
|
||||
|
||||
func ok() {
|
||||
var x = T{"check"}
|
||||
_ = x
|
||||
_ = T{"et"}
|
||||
}
|
||||
|
||||
var (
|
||||
y = T{"stare"}
|
||||
w = T{_: "look"} // ERROR "invalid field name _ in struct initializer"
|
||||
_ = T{"page"}
|
||||
_ = T{_: "out"} // ERROR "invalid field name _ in struct initializer"
|
||||
)
|
||||
|
||||
func bad() {
|
||||
var z = T{_: "verse"} // ERROR "invalid field name _ in struct initializer"
|
||||
_ = z
|
||||
_ = T{_: "itinerary"} // ERROR "invalid field name _ in struct initializer"
|
||||
}
|
Loading…
Reference in a new issue