mirror of
https://github.com/golang/go
synced 2024-11-12 03:50:21 -07:00
cmd/compile/internal/types2: report error for incomplete struct composite literal type
Mark a struct as "complete" with a non-nil (but possibly zero length) fields list. Add a test when type-checking struct composite literals, the same way we do for other composite literal types. Fixes #49276. Change-Id: If44a3d790bf7032ddcd155af49bdc47b1cdff4fc Reviewed-on: https://go-review.googlesource.com/c/go/+/361412 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
cfb3dc7710
commit
61d789db3a
@ -1260,6 +1260,12 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
|
||||
|
||||
switch utyp := structure(base).(type) {
|
||||
case *Struct:
|
||||
// Prevent crash if the struct referred to is not yet set up.
|
||||
// See analogous comment for *Array.
|
||||
if utyp.fields == nil {
|
||||
check.error(e, "illegal cycle in type declaration")
|
||||
goto Error
|
||||
}
|
||||
if len(e.ElemList) == 0 {
|
||||
break
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
|
||||
// A Struct represents a struct type.
|
||||
type Struct struct {
|
||||
fields []*Var
|
||||
fields []*Var // fields != nil indicates the struct is set up (possibly with len(fields) == 0)
|
||||
tags []string // field tags; nil if there are no tags
|
||||
}
|
||||
|
||||
@ -32,7 +32,9 @@ func NewStruct(fields []*Var, tags []string) *Struct {
|
||||
if len(tags) > len(fields) {
|
||||
panic("more tags than fields")
|
||||
}
|
||||
return &Struct{fields: fields, tags: tags}
|
||||
s := &Struct{fields: fields, tags: tags}
|
||||
s.markComplete()
|
||||
return s
|
||||
}
|
||||
|
||||
// NumFields returns the number of fields in the struct (including blank and embedded fields).
|
||||
@ -55,8 +57,15 @@ func (s *Struct) String() string { return TypeString(s, nil) }
|
||||
// ----------------------------------------------------------------------------
|
||||
// Implementation
|
||||
|
||||
func (s *Struct) markComplete() {
|
||||
if s.fields == nil {
|
||||
s.fields = make([]*Var, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
|
||||
if e.FieldList == nil {
|
||||
styp.markComplete()
|
||||
return
|
||||
}
|
||||
|
||||
@ -160,6 +169,7 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
|
||||
|
||||
styp.fields = fields
|
||||
styp.tags = tags
|
||||
styp.markComplete()
|
||||
}
|
||||
|
||||
func embeddedFieldIdent(e syntax.Expr) *syntax.Name {
|
||||
|
@ -91,7 +91,9 @@ func (subst *subster) typ(typ Type) Type {
|
||||
|
||||
case *Struct:
|
||||
if fields, copied := subst.varList(t.fields); copied {
|
||||
return &Struct{fields: fields, tags: t.tags}
|
||||
s := &Struct{fields: fields, tags: t.tags}
|
||||
s.markComplete()
|
||||
return s
|
||||
}
|
||||
|
||||
case *Pointer:
|
||||
|
46
src/cmd/compile/internal/types2/testdata/fixedbugs/issue49276.go
vendored
Normal file
46
src/cmd/compile/internal/types2/testdata/fixedbugs/issue49276.go
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
package p
|
||||
|
||||
import "unsafe"
|
||||
|
||||
type S /* ERROR illegal cycle in declaration of S */ struct {
|
||||
_ [unsafe.Sizeof(s)]byte
|
||||
}
|
||||
|
||||
var s S
|
||||
|
||||
// Since f is a pointer, this case could be valid.
|
||||
// But it's pathological and not worth the expense.
|
||||
type T struct {
|
||||
f *[unsafe.Sizeof(T /* ERROR illegal cycle in type declaration */ {})]int
|
||||
}
|
||||
|
||||
// a mutually recursive case using unsafe.Sizeof
|
||||
type (
|
||||
A1 struct {
|
||||
_ [unsafe.Sizeof(B1{})]int
|
||||
}
|
||||
|
||||
B1 struct {
|
||||
_ [unsafe.Sizeof(A1 /* ERROR illegal cycle in type declaration */ {})]int
|
||||
}
|
||||
)
|
||||
|
||||
// a mutually recursive case using len
|
||||
type (
|
||||
A2 struct {
|
||||
f [len(B2{}.f)]int
|
||||
}
|
||||
|
||||
B2 struct {
|
||||
f [len(A2 /* ERROR illegal cycle in type declaration */ {}.f)]int
|
||||
}
|
||||
)
|
||||
|
||||
// test case from issue
|
||||
type a struct {
|
||||
_ [42 - unsafe.Sizeof(a /* ERROR illegal cycle in type declaration */ {})]byte
|
||||
}
|
Loading…
Reference in New Issue
Block a user