mirror of
https://github.com/golang/go
synced 2024-10-02 00:28:33 -06:00
cmd/compile: replace TFIELD kind with separate Field type
Allows removing a bunch of unnecessary fields. Passes toolstash/buildall. Change-Id: Iec2492920e1c3ef352a9bf4296c74a55d9cc9ad6 Reviewed-on: https://go-review.googlesource.com/20677 Reviewed-by: Robert Griesemer <gri@golang.org> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
2a46b08a02
commit
2e9369067b
@ -550,7 +550,7 @@ func eqmemfunc(size int64, t *Type) (fn *Node, needsize bool) {
|
|||||||
// size is the length in bytes of the memory included in the run.
|
// size is the length in bytes of the memory included in the run.
|
||||||
// next is the index just after the end of the memory run.
|
// next is the index just after the end of the memory run.
|
||||||
// TODO(mdempsky): Eliminate fields parameter once struct fields are kept in slices.
|
// TODO(mdempsky): Eliminate fields parameter once struct fields are kept in slices.
|
||||||
func memrun(t *Type, fields []*Type, start int) (size int64, next int) {
|
func memrun(t *Type, fields []*Field, start int) (size int64, next int) {
|
||||||
next = start
|
next = start
|
||||||
for {
|
for {
|
||||||
next++
|
next++
|
||||||
@ -573,7 +573,7 @@ func memrun(t *Type, fields []*Type, start int) (size int64, next int) {
|
|||||||
// ispaddedfield reports whether the i'th field of struct type t is followed
|
// ispaddedfield reports whether the i'th field of struct type t is followed
|
||||||
// by padding. The caller is responsible for providing t.FieldSlice() as fields.
|
// by padding. The caller is responsible for providing t.FieldSlice() as fields.
|
||||||
// TODO(mdempsky): Eliminate fields parameter once struct fields are kept in slices.
|
// TODO(mdempsky): Eliminate fields parameter once struct fields are kept in slices.
|
||||||
func ispaddedfield(t *Type, fields []*Type, i int) bool {
|
func ispaddedfield(t *Type, fields []*Field, i int) bool {
|
||||||
if t.Etype != TSTRUCT {
|
if t.Etype != TSTRUCT {
|
||||||
Fatalf("ispaddedfield called non-struct %v", t)
|
Fatalf("ispaddedfield called non-struct %v", t)
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,6 @@ func Rnd(o int64, r int64) int64 {
|
|||||||
func offmod(t *Type) {
|
func offmod(t *Type) {
|
||||||
o := int32(0)
|
o := int32(0)
|
||||||
for f, it := IterFields(t); f != nil; f = it.Next() {
|
for f, it := IterFields(t); f != nil; f = it.Next() {
|
||||||
if f.Etype != TFIELD {
|
|
||||||
Fatalf("offmod: not TFIELD: %v", Tconv(f, obj.FmtLong))
|
|
||||||
}
|
|
||||||
f.Width = int64(o)
|
f.Width = int64(o)
|
||||||
o += int32(Widthptr)
|
o += int32(Widthptr)
|
||||||
if int64(o) >= Thearch.MAXWIDTH {
|
if int64(o) >= Thearch.MAXWIDTH {
|
||||||
@ -41,9 +38,6 @@ func widstruct(errtype *Type, t *Type, o int64, flag int) int64 {
|
|||||||
lastzero := int64(0)
|
lastzero := int64(0)
|
||||||
var w int64
|
var w int64
|
||||||
for f, it := IterFields(t); f != nil; f = it.Next() {
|
for f, it := IterFields(t); f != nil; f = it.Next() {
|
||||||
if f.Etype != TFIELD {
|
|
||||||
Fatalf("widstruct: not TFIELD: %v", Tconv(f, obj.FmtLong))
|
|
||||||
}
|
|
||||||
if f.Type == nil {
|
if f.Type == nil {
|
||||||
// broken field, just skip it so that other valid fields
|
// broken field, just skip it so that other valid fields
|
||||||
// get a width.
|
// get a width.
|
||||||
|
@ -433,10 +433,6 @@ func (p *exporter) typ(t *Type) {
|
|||||||
|
|
||||||
// pick off named types
|
// pick off named types
|
||||||
if sym := t.Sym; sym != nil {
|
if sym := t.Sym; sym != nil {
|
||||||
// Fields should be exported by p.field().
|
|
||||||
if t.Etype == TFIELD {
|
|
||||||
Fatalf("exporter: printing a field/parameter with wrong function")
|
|
||||||
}
|
|
||||||
// Predeclared types should have been found in the type map.
|
// Predeclared types should have been found in the type map.
|
||||||
if t.Orig == t {
|
if t.Orig == t {
|
||||||
Fatalf("exporter: predeclared type missing from type map?")
|
Fatalf("exporter: predeclared type missing from type map?")
|
||||||
@ -464,7 +460,7 @@ func (p *exporter) typ(t *Type) {
|
|||||||
// sort methods for reproducible export format
|
// sort methods for reproducible export format
|
||||||
// TODO(gri) Determine if they are already sorted
|
// TODO(gri) Determine if they are already sorted
|
||||||
// in which case we can drop this step.
|
// in which case we can drop this step.
|
||||||
var methods []*Type
|
var methods []*Field
|
||||||
for m, it := IterMethods(t); m != nil; m = it.Next() {
|
for m, it := IterMethods(t); m != nil; m = it.Next() {
|
||||||
methods = append(methods, m)
|
methods = append(methods, m)
|
||||||
}
|
}
|
||||||
@ -566,11 +562,7 @@ func (p *exporter) fieldList(t *Type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *exporter) field(f *Type) {
|
func (p *exporter) field(f *Field) {
|
||||||
if f.Etype != TFIELD {
|
|
||||||
Fatalf("exporter: field expected")
|
|
||||||
}
|
|
||||||
|
|
||||||
p.fieldName(f)
|
p.fieldName(f)
|
||||||
p.typ(f.Type)
|
p.typ(f.Type)
|
||||||
p.note(f.Note)
|
p.note(f.Note)
|
||||||
@ -599,11 +591,7 @@ func (p *exporter) methodList(t *Type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *exporter) method(m *Type) {
|
func (p *exporter) method(m *Field) {
|
||||||
if m.Etype != TFIELD {
|
|
||||||
Fatalf("exporter: method expected")
|
|
||||||
}
|
|
||||||
|
|
||||||
p.fieldName(m)
|
p.fieldName(m)
|
||||||
// TODO(gri) For functions signatures, we use p.typ() to export
|
// TODO(gri) For functions signatures, we use p.typ() to export
|
||||||
// so we could share the same type with multiple functions. Do
|
// so we could share the same type with multiple functions. Do
|
||||||
@ -614,13 +602,13 @@ func (p *exporter) method(m *Type) {
|
|||||||
|
|
||||||
// fieldName is like qualifiedName but it doesn't record the package
|
// fieldName is like qualifiedName but it doesn't record the package
|
||||||
// for blank (_) or exported names.
|
// for blank (_) or exported names.
|
||||||
func (p *exporter) fieldName(t *Type) {
|
func (p *exporter) fieldName(t *Field) {
|
||||||
sym := t.Sym
|
sym := t.Sym
|
||||||
|
|
||||||
var name string
|
var name string
|
||||||
if t.Embedded == 0 {
|
if t.Embedded == 0 {
|
||||||
name = sym.Name
|
name = sym.Name
|
||||||
} else if bname := basetypeName(t); bname != "" && !exportname(bname) {
|
} else if bname := basetypeName(t.Type); bname != "" && !exportname(bname) {
|
||||||
// anonymous field with unexported base type name: use "?" as field name
|
// anonymous field with unexported base type name: use "?" as field name
|
||||||
// (bname != "" per spec, but we are conservative in case of errors)
|
// (bname != "" per spec, but we are conservative in case of errors)
|
||||||
name = "?"
|
name = "?"
|
||||||
@ -661,10 +649,7 @@ func (p *exporter) paramList(params *Type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *exporter) param(q *Type, n int) {
|
func (p *exporter) param(q *Field, n int) {
|
||||||
if q.Etype != TFIELD {
|
|
||||||
Fatalf("exporter: parameter expected")
|
|
||||||
}
|
|
||||||
t := q.Type
|
t := q.Type
|
||||||
if q.Isddd {
|
if q.Isddd {
|
||||||
// create a fake type to encode ... just for the p.typ call
|
// create a fake type to encode ... just for the p.typ call
|
||||||
@ -685,7 +670,7 @@ func (p *exporter) param(q *Type, n int) {
|
|||||||
p.note(q.Note)
|
p.note(q.Note)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parName(q *Type) string {
|
func parName(q *Field) string {
|
||||||
if q.Sym == nil {
|
if q.Sym == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -2225,9 +2225,9 @@ func stkof(n *Node) int64 {
|
|||||||
t = t.Type
|
t = t.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
t = t.Results().Field(0)
|
f := t.Results().Field(0)
|
||||||
if t != nil {
|
if f != nil {
|
||||||
return t.Width + Ctxt.FixedFrameSize()
|
return f.Width + Ctxt.FixedFrameSize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,13 +297,13 @@ func transformclosure(xfunc *Node) {
|
|||||||
f := xfunc.Func.Nname
|
f := xfunc.Func.Nname
|
||||||
|
|
||||||
// We are going to insert captured variables before input args.
|
// We are going to insert captured variables before input args.
|
||||||
var params []*Type
|
var params []*Field
|
||||||
var decls []*Node
|
var decls []*Node
|
||||||
for _, v := range func_.Func.Cvars.Slice() {
|
for _, v := range func_.Func.Cvars.Slice() {
|
||||||
if v.Op == OXXX {
|
if v.Op == OXXX {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fld := typ(TFIELD)
|
fld := newField()
|
||||||
fld.Funarg = true
|
fld.Funarg = true
|
||||||
if v.Name.Byval {
|
if v.Name.Byval {
|
||||||
// If v is captured by value, we merely downgrade it to PPARAM.
|
// If v is captured by value, we merely downgrade it to PPARAM.
|
||||||
|
@ -744,7 +744,7 @@ func checkembeddedtype(t *Type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func structfield(n *Node) *Type {
|
func structfield(n *Node) *Field {
|
||||||
lno := lineno
|
lno := lineno
|
||||||
lineno = n.Lineno
|
lineno = n.Lineno
|
||||||
|
|
||||||
@ -752,7 +752,7 @@ func structfield(n *Node) *Type {
|
|||||||
Fatalf("structfield: oops %v\n", n)
|
Fatalf("structfield: oops %v\n", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
f := typ(TFIELD)
|
f := newField()
|
||||||
f.Isddd = n.Isddd
|
f.Isddd = n.Isddd
|
||||||
|
|
||||||
if n.Right != nil {
|
if n.Right != nil {
|
||||||
@ -832,7 +832,7 @@ func tostruct0(t *Type, l []*Node) {
|
|||||||
Fatalf("struct expected")
|
Fatalf("struct expected")
|
||||||
}
|
}
|
||||||
|
|
||||||
var fields []*Type
|
var fields []*Field
|
||||||
for _, n := range l {
|
for _, n := range l {
|
||||||
fields = append(fields, structfield(n))
|
fields = append(fields, structfield(n))
|
||||||
}
|
}
|
||||||
@ -855,7 +855,7 @@ func tofunargs(l []*Node) *Type {
|
|||||||
t := typ(TSTRUCT)
|
t := typ(TSTRUCT)
|
||||||
t.Funarg = true
|
t.Funarg = true
|
||||||
|
|
||||||
var fields []*Type
|
var fields []*Field
|
||||||
for _, n := range l {
|
for _, n := range l {
|
||||||
f := structfield(n)
|
f := structfield(n)
|
||||||
f.Funarg = true
|
f.Funarg = true
|
||||||
@ -878,7 +878,7 @@ func tofunargs(l []*Node) *Type {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func interfacefield(n *Node) *Type {
|
func interfacefield(n *Node) *Field {
|
||||||
lno := lineno
|
lno := lineno
|
||||||
lineno = n.Lineno
|
lineno = n.Lineno
|
||||||
|
|
||||||
@ -890,7 +890,7 @@ func interfacefield(n *Node) *Type {
|
|||||||
Yyerror("interface method cannot have annotation")
|
Yyerror("interface method cannot have annotation")
|
||||||
}
|
}
|
||||||
|
|
||||||
f := typ(TFIELD)
|
f := newField()
|
||||||
f.Isddd = n.Isddd
|
f.Isddd = n.Isddd
|
||||||
|
|
||||||
if n.Right != nil {
|
if n.Right != nil {
|
||||||
@ -956,14 +956,14 @@ func tointerface0(t *Type, l []*Node) *Type {
|
|||||||
Fatalf("interface expected")
|
Fatalf("interface expected")
|
||||||
}
|
}
|
||||||
|
|
||||||
var fields []*Type
|
var fields []*Field
|
||||||
for _, n := range l {
|
for _, n := range l {
|
||||||
f := interfacefield(n)
|
f := interfacefield(n)
|
||||||
|
|
||||||
if n.Left == nil && f.Type.Etype == TINTER {
|
if n.Left == nil && f.Type.Etype == TINTER {
|
||||||
// embedded interface, inline methods
|
// embedded interface, inline methods
|
||||||
for t1, it := IterFields(f.Type); t1 != nil; t1 = it.Next() {
|
for t1, it := IterFields(f.Type); t1 != nil; t1 = it.Next() {
|
||||||
f = typ(TFIELD)
|
f = newField()
|
||||||
f.Type = t1.Type
|
f.Type = t1.Type
|
||||||
f.Broke = t1.Broke
|
f.Broke = t1.Broke
|
||||||
f.Sym = t1.Sym
|
f.Sym = t1.Sym
|
||||||
@ -1295,15 +1295,15 @@ func addmethod(msym *Sym, t *Type, tpkg *Pkg, local, nointerface bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get parent type sym
|
// get parent type sym
|
||||||
pa := t.Recv() // ptr to this structure
|
rf := t.Recv() // ptr to this structure
|
||||||
if pa == nil {
|
if rf == nil {
|
||||||
Yyerror("missing receiver")
|
Yyerror("missing receiver")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pa = pa.Type // base type
|
pa := rf.Type // base type
|
||||||
f := methtype(pa, 1)
|
mt := methtype(pa, 1)
|
||||||
if f == nil {
|
if mt == nil {
|
||||||
t = pa
|
t = pa
|
||||||
if t == nil { // rely on typecheck having complained before
|
if t == nil { // rely on typecheck having complained before
|
||||||
return
|
return
|
||||||
@ -1344,7 +1344,7 @@ func addmethod(msym *Sym, t *Type, tpkg *Pkg, local, nointerface bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pa = f
|
pa = mt
|
||||||
if local && !pa.Local {
|
if local && !pa.Local {
|
||||||
Yyerror("cannot define new methods on non-local type %v", pa)
|
Yyerror("cannot define new methods on non-local type %v", pa)
|
||||||
return
|
return
|
||||||
@ -1366,12 +1366,9 @@ func addmethod(msym *Sym, t *Type, tpkg *Pkg, local, nointerface bool) {
|
|||||||
n := Nod(ODCLFIELD, newname(msym), nil)
|
n := Nod(ODCLFIELD, newname(msym), nil)
|
||||||
n.Type = t
|
n.Type = t
|
||||||
|
|
||||||
var d *Type // last found
|
var d *Field // last found
|
||||||
for f, it := IterMethods(pa); f != nil; f = it.Next() {
|
for f, it := IterMethods(pa); f != nil; f = it.Next() {
|
||||||
d = f
|
d = f
|
||||||
if f.Etype != TFIELD {
|
|
||||||
Fatalf("addmethod: not TFIELD: %v", Tconv(f, obj.FmtLong))
|
|
||||||
}
|
|
||||||
if msym.Name != f.Sym.Name {
|
if msym.Name != f.Sym.Name {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -1381,7 +1378,7 @@ func addmethod(msym *Sym, t *Type, tpkg *Pkg, local, nointerface bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f = structfield(n)
|
f := structfield(n)
|
||||||
f.Nointerface = nointerface
|
f.Nointerface = nointerface
|
||||||
|
|
||||||
// during import unexported method names should be in the type's package
|
// during import unexported method names should be in the type's package
|
||||||
|
@ -273,7 +273,7 @@ func dumpexportvar(s *Sym) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// methodbyname sorts types by symbol name.
|
// methodbyname sorts types by symbol name.
|
||||||
type methodbyname []*Type
|
type methodbyname []*Field
|
||||||
|
|
||||||
func (x methodbyname) Len() int { return len(x) }
|
func (x methodbyname) Len() int { return len(x) }
|
||||||
func (x methodbyname) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
func (x methodbyname) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||||
@ -283,9 +283,6 @@ func dumpexporttype(t *Type) {
|
|||||||
if t == nil {
|
if t == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if t.Etype == TFIELD {
|
|
||||||
Fatalf("unexpected TFIELD in dumpexporttype")
|
|
||||||
}
|
|
||||||
if t.Printed || t == Types[t.Etype] || t == bytetype || t == runetype || t == errortype {
|
if t.Printed || t == Types[t.Etype] || t == bytetype || t == runetype || t == errortype {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -315,7 +312,7 @@ func dumpexporttype(t *Type) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var m []*Type
|
var m []*Field
|
||||||
for f, it := IterMethods(t); f != nil; f = it.Next() {
|
for f, it := IterMethods(t); f != nil; f = it.Next() {
|
||||||
dumpexporttype(f.Type)
|
dumpexporttype(f.Type)
|
||||||
m = append(m, f)
|
m = append(m, f)
|
||||||
@ -334,10 +331,10 @@ func dumpexporttype(t *Type) {
|
|||||||
if Debug['l'] < 2 {
|
if Debug['l'] < 2 {
|
||||||
typecheckinl(f.Type.Nname)
|
typecheckinl(f.Type.Nname)
|
||||||
}
|
}
|
||||||
exportf("\tfunc (%v) %v %v { %v }\n", Tconv(f.Type.Recv(), obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp), Hconv(f.Type.Nname.Func.Inl, obj.FmtSharp))
|
exportf("\tfunc %v %v %v { %v }\n", Tconv(f.Type.Recvs(), obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp), Hconv(f.Type.Nname.Func.Inl, obj.FmtSharp))
|
||||||
reexportdeplist(f.Type.Nname.Func.Inl)
|
reexportdeplist(f.Type.Nname.Func.Inl)
|
||||||
} else {
|
} else {
|
||||||
exportf("\tfunc (%v) %v %v\n", Tconv(f.Type.Recv(), obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp))
|
exportf("\tfunc %v %v %v\n", Tconv(f.Type.Recvs(), obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -401,7 +401,6 @@ var etnames = []string{
|
|||||||
TMAP: "MAP",
|
TMAP: "MAP",
|
||||||
TINTER: "INTER",
|
TINTER: "INTER",
|
||||||
TFORW: "FORW",
|
TFORW: "FORW",
|
||||||
TFIELD: "FIELD",
|
|
||||||
TSTRING: "STRING",
|
TSTRING: "STRING",
|
||||||
TUNSAFEPTR: "TUNSAFEPTR",
|
TUNSAFEPTR: "TUNSAFEPTR",
|
||||||
TANY: "ANY",
|
TANY: "ANY",
|
||||||
@ -510,7 +509,7 @@ func typefmt(t *Type, flag int) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unless the 'l' flag was specified, if the type has a name, just print that name.
|
// Unless the 'l' flag was specified, if the type has a name, just print that name.
|
||||||
if flag&obj.FmtLong == 0 && t.Sym != nil && t.Etype != TFIELD && t != Types[t.Etype] {
|
if flag&obj.FmtLong == 0 && t.Sym != nil && t != Types[t.Etype] {
|
||||||
switch fmtmode {
|
switch fmtmode {
|
||||||
case FTypeId:
|
case FTypeId:
|
||||||
if flag&obj.FmtShort != 0 {
|
if flag&obj.FmtShort != 0 {
|
||||||
@ -664,14 +663,14 @@ func typefmt(t *Type, flag int) string {
|
|||||||
buf.WriteString("(")
|
buf.WriteString("(")
|
||||||
if fmtmode == FTypeId || fmtmode == FErr { // no argument names on function signature, and no "noescape"/"nosplit" tags
|
if fmtmode == FTypeId || fmtmode == FErr { // no argument names on function signature, and no "noescape"/"nosplit" tags
|
||||||
for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
|
for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
|
||||||
buf.WriteString(Tconv(t1, obj.FmtShort))
|
buf.WriteString(Fldconv(t1, obj.FmtShort))
|
||||||
if t1.Down != nil {
|
if t1.Down != nil {
|
||||||
buf.WriteString(", ")
|
buf.WriteString(", ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
|
for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
|
||||||
buf.WriteString(Tconv(t1, 0))
|
buf.WriteString(Fldconv(t1, 0))
|
||||||
if t1.Down != nil {
|
if t1.Down != nil {
|
||||||
buf.WriteString(", ")
|
buf.WriteString(", ")
|
||||||
}
|
}
|
||||||
@ -682,7 +681,7 @@ func typefmt(t *Type, flag int) string {
|
|||||||
buf.WriteString("struct {")
|
buf.WriteString("struct {")
|
||||||
for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
|
for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
|
||||||
buf.WriteString(" ")
|
buf.WriteString(" ")
|
||||||
buf.WriteString(Tconv(t1, obj.FmtLong))
|
buf.WriteString(Fldconv(t1, obj.FmtLong))
|
||||||
if t1.Down != nil {
|
if t1.Down != nil {
|
||||||
buf.WriteString(";")
|
buf.WriteString(";")
|
||||||
}
|
}
|
||||||
@ -694,72 +693,6 @@ func typefmt(t *Type, flag int) string {
|
|||||||
}
|
}
|
||||||
return buf.String()
|
return buf.String()
|
||||||
|
|
||||||
case TFIELD:
|
|
||||||
var name string
|
|
||||||
if flag&obj.FmtShort == 0 {
|
|
||||||
s := t.Sym
|
|
||||||
|
|
||||||
// Take the name from the original, lest we substituted it with ~r%d or ~b%d.
|
|
||||||
// ~r%d is a (formerly) unnamed result.
|
|
||||||
if (fmtmode == FErr || fmtmode == FExp) && t.Nname != nil {
|
|
||||||
if t.Nname.Orig != nil {
|
|
||||||
s = t.Nname.Orig.Sym
|
|
||||||
if s != nil && s.Name[0] == '~' {
|
|
||||||
if s.Name[1] == 'r' { // originally an unnamed result
|
|
||||||
s = nil
|
|
||||||
} else if s.Name[1] == 'b' { // originally the blank identifier _
|
|
||||||
s = Lookup("_")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
s = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if s != nil && t.Embedded == 0 {
|
|
||||||
if t.Funarg {
|
|
||||||
name = Nconv(t.Nname, 0)
|
|
||||||
} else if flag&obj.FmtLong != 0 {
|
|
||||||
name = Sconv(s, obj.FmtShort|obj.FmtByte) // qualify non-exported names (used on structs, not on funarg)
|
|
||||||
} else {
|
|
||||||
name = Sconv(s, 0)
|
|
||||||
}
|
|
||||||
} else if fmtmode == FExp {
|
|
||||||
// TODO(rsc) this breaks on the eliding of unused arguments in the backend
|
|
||||||
// when this is fixed, the special case in dcl.go checkarglist can go.
|
|
||||||
//if(t->funarg)
|
|
||||||
// fmtstrcpy(fp, "_ ");
|
|
||||||
//else
|
|
||||||
if t.Embedded != 0 && s.Pkg != nil && len(s.Pkg.Path) > 0 {
|
|
||||||
name = fmt.Sprintf("@%q.?", s.Pkg.Path)
|
|
||||||
} else {
|
|
||||||
name = "?"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var typ string
|
|
||||||
if t.Isddd {
|
|
||||||
typ = "..." + Tconv(t.Type.Type, 0)
|
|
||||||
} else {
|
|
||||||
typ = Tconv(t.Type, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
str := typ
|
|
||||||
if name != "" {
|
|
||||||
str = name + " " + typ
|
|
||||||
}
|
|
||||||
|
|
||||||
// The fmtbody flag is intended to suppress escape analysis annotations
|
|
||||||
// when printing a function type used in a function body.
|
|
||||||
// (The escape analysis tags do not apply to func vars.)
|
|
||||||
// But it must not suppress struct field tags.
|
|
||||||
// See golang.org/issue/13777 and golang.org/issue/14331.
|
|
||||||
if flag&obj.FmtShort == 0 && (!fmtbody || !t.Funarg) && t.Note != nil {
|
|
||||||
str += " " + strconv.Quote(*t.Note)
|
|
||||||
}
|
|
||||||
return str
|
|
||||||
|
|
||||||
case TFORW:
|
case TFORW:
|
||||||
if t.Sym != nil {
|
if t.Sym != nil {
|
||||||
return fmt.Sprintf("undefined %v", t.Sym)
|
return fmt.Sprintf("undefined %v", t.Sym)
|
||||||
@ -1627,6 +1560,95 @@ func (t *Type) String() string {
|
|||||||
return Tconv(t, 0)
|
return Tconv(t, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Fldconv(f *Field, flag int) string {
|
||||||
|
if f == nil {
|
||||||
|
return "<T>"
|
||||||
|
}
|
||||||
|
|
||||||
|
sf := flag
|
||||||
|
sm, sb := setfmode(&flag)
|
||||||
|
|
||||||
|
if fmtmode == FTypeId && (sf&obj.FmtUnsigned != 0) {
|
||||||
|
fmtpkgpfx++
|
||||||
|
}
|
||||||
|
if fmtpkgpfx != 0 {
|
||||||
|
flag |= obj.FmtUnsigned
|
||||||
|
}
|
||||||
|
|
||||||
|
var name string
|
||||||
|
if flag&obj.FmtShort == 0 {
|
||||||
|
s := f.Sym
|
||||||
|
|
||||||
|
// Take the name from the original, lest we substituted it with ~r%d or ~b%d.
|
||||||
|
// ~r%d is a (formerly) unnamed result.
|
||||||
|
if (fmtmode == FErr || fmtmode == FExp) && f.Nname != nil {
|
||||||
|
if f.Nname.Orig != nil {
|
||||||
|
s = f.Nname.Orig.Sym
|
||||||
|
if s != nil && s.Name[0] == '~' {
|
||||||
|
if s.Name[1] == 'r' { // originally an unnamed result
|
||||||
|
s = nil
|
||||||
|
} else if s.Name[1] == 'b' { // originally the blank identifier _
|
||||||
|
s = Lookup("_")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if s != nil && f.Embedded == 0 {
|
||||||
|
if f.Funarg {
|
||||||
|
name = Nconv(f.Nname, 0)
|
||||||
|
} else if flag&obj.FmtLong != 0 {
|
||||||
|
name = Sconv(s, obj.FmtShort|obj.FmtByte) // qualify non-exported names (used on structs, not on funarg)
|
||||||
|
} else {
|
||||||
|
name = Sconv(s, 0)
|
||||||
|
}
|
||||||
|
} else if fmtmode == FExp {
|
||||||
|
// TODO(rsc) this breaks on the eliding of unused arguments in the backend
|
||||||
|
// when this is fixed, the special case in dcl.go checkarglist can go.
|
||||||
|
//if(t->funarg)
|
||||||
|
// fmtstrcpy(fp, "_ ");
|
||||||
|
//else
|
||||||
|
if f.Embedded != 0 && s.Pkg != nil && len(s.Pkg.Path) > 0 {
|
||||||
|
name = fmt.Sprintf("@%q.?", s.Pkg.Path)
|
||||||
|
} else {
|
||||||
|
name = "?"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var typ string
|
||||||
|
if f.Isddd {
|
||||||
|
typ = "..." + Tconv(f.Type.Type, 0)
|
||||||
|
} else {
|
||||||
|
typ = Tconv(f.Type, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
str := typ
|
||||||
|
if name != "" {
|
||||||
|
str = name + " " + typ
|
||||||
|
}
|
||||||
|
|
||||||
|
// The fmtbody flag is intended to suppress escape analysis annotations
|
||||||
|
// when printing a function type used in a function body.
|
||||||
|
// (The escape analysis tags do not apply to func vars.)
|
||||||
|
// But it must not suppress struct field tags.
|
||||||
|
// See golang.org/issue/13777 and golang.org/issue/14331.
|
||||||
|
if flag&obj.FmtShort == 0 && (!fmtbody || !f.Funarg) && f.Note != nil {
|
||||||
|
str += " " + strconv.Quote(*f.Note)
|
||||||
|
}
|
||||||
|
|
||||||
|
if fmtmode == FTypeId && (sf&obj.FmtUnsigned != 0) {
|
||||||
|
fmtpkgpfx--
|
||||||
|
}
|
||||||
|
|
||||||
|
flag = sf
|
||||||
|
fmtbody = sb
|
||||||
|
fmtmode = sm
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
// Fmt "%T": types.
|
// Fmt "%T": types.
|
||||||
// Flags: 'l' print definition, not name
|
// Flags: 'l' print definition, not name
|
||||||
// 'h' omit 'func' and receiver from function types, short type names
|
// 'h' omit 'func' and receiver from function types, short type names
|
||||||
|
@ -1235,9 +1235,6 @@ func visitComponents(t *Type, startOffset int64, f func(elem *Type, elemOffset i
|
|||||||
}
|
}
|
||||||
|
|
||||||
for field, it := IterFields(t); field != nil; field = it.Next() {
|
for field, it := IterFields(t); field != nil; field = it.Next() {
|
||||||
if field.Etype != TFIELD {
|
|
||||||
Fatalf("bad struct")
|
|
||||||
}
|
|
||||||
if !visitComponents(field.Type, startOffset+field.Width, f) {
|
if !visitComponents(field.Type, startOffset+field.Width, f) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -531,11 +531,15 @@ func newplist() *obj.Plist {
|
|||||||
// incorrectly) passed a 1; the behavior is exactly
|
// incorrectly) passed a 1; the behavior is exactly
|
||||||
// the same as it is for 1, except that PARAMOUT is
|
// the same as it is for 1, except that PARAMOUT is
|
||||||
// generated instead of PARAM.
|
// generated instead of PARAM.
|
||||||
func nodarg(t *Type, fp int) *Node {
|
func nodarg(t interface{}, fp int) *Node {
|
||||||
var n *Node
|
var n *Node
|
||||||
|
|
||||||
// entire argument struct, not just one arg
|
switch t := t.(type) {
|
||||||
if t.Etype == TSTRUCT && t.Funarg {
|
case *Type:
|
||||||
|
// entire argument struct, not just one arg
|
||||||
|
if t.Etype != TSTRUCT || !t.Funarg {
|
||||||
|
Fatalf("nodarg: bad type %v", t)
|
||||||
|
}
|
||||||
n = Nod(ONAME, nil, nil)
|
n = Nod(ONAME, nil, nil)
|
||||||
n.Sym = Lookup(".args")
|
n.Sym = Lookup(".args")
|
||||||
n.Type = t
|
n.Type = t
|
||||||
@ -548,36 +552,31 @@ func nodarg(t *Type, fp int) *Node {
|
|||||||
}
|
}
|
||||||
n.Xoffset = first.Width
|
n.Xoffset = first.Width
|
||||||
n.Addable = true
|
n.Addable = true
|
||||||
goto fp
|
case *Field:
|
||||||
}
|
if fp == 1 || fp == -1 {
|
||||||
|
for _, n := range Curfn.Func.Dcl {
|
||||||
if t.Etype != TFIELD {
|
if (n.Class == PPARAM || n.Class == PPARAMOUT) && !isblanksym(t.Sym) && n.Sym == t.Sym {
|
||||||
Fatalf("nodarg: not field %v", t)
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
if fp == 1 || fp == -1 {
|
|
||||||
for _, n := range Curfn.Func.Dcl {
|
|
||||||
if (n.Class == PPARAM || n.Class == PPARAMOUT) && !isblanksym(t.Sym) && n.Sym == t.Sym {
|
|
||||||
return n
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
n = Nod(ONAME, nil, nil)
|
n = Nod(ONAME, nil, nil)
|
||||||
n.Type = t.Type
|
n.Type = t.Type
|
||||||
n.Sym = t.Sym
|
n.Sym = t.Sym
|
||||||
|
if t.Width == BADWIDTH {
|
||||||
if t.Width == BADWIDTH {
|
Fatalf("nodarg: offset not computed for %v", t)
|
||||||
Fatalf("nodarg: offset not computed for %v", t)
|
}
|
||||||
|
n.Xoffset = t.Width
|
||||||
|
n.Addable = true
|
||||||
|
n.Orig = t.Nname
|
||||||
|
default:
|
||||||
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
n.Xoffset = t.Width
|
|
||||||
n.Addable = true
|
|
||||||
n.Orig = t.Nname
|
|
||||||
|
|
||||||
// Rewrite argument named _ to __,
|
// Rewrite argument named _ to __,
|
||||||
// or else the assignment to _ will be
|
// or else the assignment to _ will be
|
||||||
// discarded during code generation.
|
// discarded during code generation.
|
||||||
fp:
|
|
||||||
if isblank(n) {
|
if isblank(n) {
|
||||||
n.Sym = Lookup("__")
|
n.Sym = Lookup("__")
|
||||||
}
|
}
|
||||||
|
@ -497,7 +497,7 @@ func mkinlcall(np **Node, fn *Node, isddd bool) {
|
|||||||
safemode = save_safemode
|
safemode = save_safemode
|
||||||
}
|
}
|
||||||
|
|
||||||
func tinlvar(t *Type) *Node {
|
func tinlvar(t *Field) *Node {
|
||||||
if t.Nname != nil && !isblank(t.Nname) {
|
if t.Nname != nil && !isblank(t.Nname) {
|
||||||
if t.Nname.Name.Inlvar == nil {
|
if t.Nname.Name.Inlvar == nil {
|
||||||
Fatalf("missing inlvar for %v\n", t.Nname)
|
Fatalf("missing inlvar for %v\n", t.Nname)
|
||||||
@ -852,7 +852,7 @@ func inlvar(var_ *Node) *Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Synthesize a variable to store the inlined function's results in.
|
// Synthesize a variable to store the inlined function's results in.
|
||||||
func retvar(t *Type, i int) *Node {
|
func retvar(t *Field, i int) *Node {
|
||||||
n := newname(Lookupf("~r%d", i))
|
n := newname(Lookupf("~r%d", i))
|
||||||
n.Type = t.Type
|
n.Type = t.Type
|
||||||
n.Class = PAUTO
|
n.Class = PAUTO
|
||||||
|
@ -62,8 +62,8 @@ func uncommonSize(t *Type) int { // Sizeof(runtime.uncommontype{})
|
|||||||
return 2*Widthptr + 2*Widthint
|
return 2*Widthptr + 2*Widthint
|
||||||
}
|
}
|
||||||
|
|
||||||
func makefield(name string, t *Type) *Type {
|
func makefield(name string, t *Type) *Field {
|
||||||
f := typ(TFIELD)
|
f := newField()
|
||||||
f.Type = t
|
f.Type = t
|
||||||
f.Sym = nopkg.Lookup(name)
|
f.Sym = nopkg.Lookup(name)
|
||||||
return f
|
return f
|
||||||
@ -91,7 +91,7 @@ func mapbucket(t *Type) *Type {
|
|||||||
|
|
||||||
arr.Type = Types[TUINT8]
|
arr.Type = Types[TUINT8]
|
||||||
arr.Bound = BUCKETSIZE
|
arr.Bound = BUCKETSIZE
|
||||||
field := make([]*Type, 0, 5)
|
field := make([]*Field, 0, 5)
|
||||||
field = append(field, makefield("topbits", arr))
|
field = append(field, makefield("topbits", arr))
|
||||||
arr = typ(TARRAY)
|
arr = typ(TARRAY)
|
||||||
arr.Type = keytype
|
arr.Type = keytype
|
||||||
@ -162,7 +162,7 @@ func hmap(t *Type) *Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bucket := mapbucket(t)
|
bucket := mapbucket(t)
|
||||||
var field [8]*Type
|
var field [8]*Field
|
||||||
field[0] = makefield("count", Types[TINT])
|
field[0] = makefield("count", Types[TINT])
|
||||||
field[1] = makefield("flags", Types[TUINT8])
|
field[1] = makefield("flags", Types[TUINT8])
|
||||||
field[2] = makefield("B", Types[TUINT8])
|
field[2] = makefield("B", Types[TUINT8])
|
||||||
@ -203,7 +203,7 @@ func hiter(t *Type) *Type {
|
|||||||
// checkBucket uintptr
|
// checkBucket uintptr
|
||||||
// }
|
// }
|
||||||
// must match ../../../../runtime/hashmap.go:hiter.
|
// must match ../../../../runtime/hashmap.go:hiter.
|
||||||
var field [12]*Type
|
var field [12]*Field
|
||||||
field[0] = makefield("key", Ptrto(t.Key()))
|
field[0] = makefield("key", Ptrto(t.Key()))
|
||||||
field[1] = makefield("val", Ptrto(t.Type))
|
field[1] = makefield("val", Ptrto(t.Type))
|
||||||
field[2] = makefield("t", Ptrto(Types[TUINT8]))
|
field[2] = makefield("t", Ptrto(Types[TUINT8]))
|
||||||
@ -286,9 +286,6 @@ func methods(t *Type) []*Sig {
|
|||||||
// generating code if necessary.
|
// generating code if necessary.
|
||||||
var ms []*Sig
|
var ms []*Sig
|
||||||
for f, it2 := IterAllMethods(mt); f != nil; f = it2.Next() {
|
for f, it2 := IterAllMethods(mt); f != nil; f = it2.Next() {
|
||||||
if f.Etype != TFIELD {
|
|
||||||
Fatalf("methods: not field %v", f)
|
|
||||||
}
|
|
||||||
if f.Type.Etype != TFUNC || f.Type.Thistuple == 0 {
|
if f.Type.Etype != TFUNC || f.Type.Thistuple == 0 {
|
||||||
Fatalf("non-method on %v method %v %v\n", mt, f.Sym, f)
|
Fatalf("non-method on %v method %v %v\n", mt, f.Sym, f)
|
||||||
}
|
}
|
||||||
@ -360,9 +357,6 @@ func methods(t *Type) []*Sig {
|
|||||||
func imethods(t *Type) []*Sig {
|
func imethods(t *Type) []*Sig {
|
||||||
var methods []*Sig
|
var methods []*Sig
|
||||||
for f, it := IterFields(t); f != nil; f = it.Next() {
|
for f, it := IterFields(t); f != nil; f = it.Next() {
|
||||||
if f.Etype != TFIELD {
|
|
||||||
Fatalf("imethods: not field")
|
|
||||||
}
|
|
||||||
if f.Type.Etype != TFUNC || f.Sym == nil {
|
if f.Type.Etype != TFUNC || f.Sym == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -623,9 +617,6 @@ func haspointers(t *Type) bool {
|
|||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
ret = true
|
ret = true
|
||||||
|
|
||||||
case TFIELD:
|
|
||||||
Fatalf("haspointers: unexpected type, %v", t)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Haspointers = 1 + uint8(obj.Bool2int(ret))
|
t.Haspointers = 1 + uint8(obj.Bool2int(ret))
|
||||||
@ -667,7 +658,7 @@ func typeptrdata(t *Type) int64 {
|
|||||||
|
|
||||||
case TSTRUCT:
|
case TSTRUCT:
|
||||||
// Find the last field that has pointers.
|
// Find the last field that has pointers.
|
||||||
var lastPtrField *Type
|
var lastPtrField *Field
|
||||||
for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
|
for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
|
||||||
if haspointers(t1.Type) {
|
if haspointers(t1.Type) {
|
||||||
lastPtrField = t1
|
lastPtrField = t1
|
||||||
@ -800,7 +791,7 @@ func typesym(t *Type) *Sym {
|
|||||||
|
|
||||||
// tracksym returns the symbol for tracking use of field/method f, assumed
|
// tracksym returns the symbol for tracking use of field/method f, assumed
|
||||||
// to be a member of struct/interface type t.
|
// to be a member of struct/interface type t.
|
||||||
func tracksym(t, f *Type) *Sym {
|
func tracksym(t *Type, f *Field) *Sym {
|
||||||
return Pkglookup(Tconv(t, obj.FmtLeft)+"."+f.Sym.Name, trackpkg)
|
return Pkglookup(Tconv(t, obj.FmtLeft)+"."+f.Sym.Name, trackpkg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -869,11 +869,11 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
|||||||
syma := Lookup("a")
|
syma := Lookup("a")
|
||||||
symb := Lookup("b")
|
symb := Lookup("b")
|
||||||
|
|
||||||
var fields [2]*Type
|
var fields [2]*Field
|
||||||
fields[0] = typ(TFIELD)
|
fields[0] = newField()
|
||||||
fields[0].Type = tk
|
fields[0].Type = tk
|
||||||
fields[0].Sym = syma
|
fields[0].Sym = syma
|
||||||
fields[1] = typ(TFIELD)
|
fields[1] = newField()
|
||||||
fields[1].Type = tv
|
fields[1].Type = tv
|
||||||
fields[1].Sym = symb
|
fields[1].Sym = symb
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ func TestSizeof(t *testing.T) {
|
|||||||
{Name{}, 52, 80},
|
{Name{}, 52, 80},
|
||||||
{Node{}, 92, 144},
|
{Node{}, 92, 144},
|
||||||
{Sym{}, 60, 112},
|
{Sym{}, 60, 112},
|
||||||
{Type{}, 140, 232},
|
{Type{}, 132, 224},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -3943,9 +3943,6 @@ func fieldIdx(n *Node) int64 {
|
|||||||
|
|
||||||
var i int64
|
var i int64
|
||||||
for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
|
for t1, it := IterFields(t); t1 != nil; t1 = it.Next() {
|
||||||
if t1.Etype != TFIELD {
|
|
||||||
panic("non-TFIELD in TSTRUCT")
|
|
||||||
}
|
|
||||||
if t1.Sym != f.Sym {
|
if t1.Sym != f.Sym {
|
||||||
i++
|
i++
|
||||||
continue
|
continue
|
||||||
|
@ -388,7 +388,7 @@ func maptype(key *Type, val *Type) *Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// methcmp sorts by symbol, then by package path for unexported symbols.
|
// methcmp sorts by symbol, then by package path for unexported symbols.
|
||||||
type methcmp []*Type
|
type methcmp []*Field
|
||||||
|
|
||||||
func (x methcmp) Len() int { return len(x) }
|
func (x methcmp) Len() int { return len(x) }
|
||||||
func (x methcmp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
func (x methcmp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||||
@ -770,17 +770,17 @@ func eqtypenoname(t1 *Type, t2 *Type) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
t1, i1 := IterFields(t1)
|
f1, i1 := IterFields(t1)
|
||||||
t2, i2 := IterFields(t2)
|
f2, i2 := IterFields(t2)
|
||||||
for {
|
for {
|
||||||
if !Eqtype(t1, t2) {
|
if !Eqtype(f1.Type, f2.Type) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if t1 == nil {
|
if f1 == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
t1 = i1.Next()
|
f1 = i1.Next()
|
||||||
t2 = i2.Next()
|
f2 = i2.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -822,9 +822,8 @@ func assignop(src *Type, dst *Type, why *string) Op {
|
|||||||
|
|
||||||
// 3. dst is an interface type and src implements dst.
|
// 3. dst is an interface type and src implements dst.
|
||||||
if dst.Etype == TINTER && src.Etype != TNIL {
|
if dst.Etype == TINTER && src.Etype != TNIL {
|
||||||
var missing *Type
|
var missing, have *Field
|
||||||
var ptr int
|
var ptr int
|
||||||
var have *Type
|
|
||||||
if implements(src, dst, &missing, &have, &ptr) {
|
if implements(src, dst, &missing, &have, &ptr) {
|
||||||
return OCONVIFACE
|
return OCONVIFACE
|
||||||
}
|
}
|
||||||
@ -861,9 +860,8 @@ func assignop(src *Type, dst *Type, why *string) Op {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if src.Etype == TINTER && dst.Etype != TBLANK {
|
if src.Etype == TINTER && dst.Etype != TBLANK {
|
||||||
var have *Type
|
var missing, have *Field
|
||||||
var ptr int
|
var ptr int
|
||||||
var missing *Type
|
|
||||||
if why != nil && implements(dst, src, &missing, &have, &ptr) {
|
if why != nil && implements(dst, src, &missing, &have, &ptr) {
|
||||||
*why = ": need type assertion"
|
*why = ": need type assertion"
|
||||||
}
|
}
|
||||||
@ -1096,7 +1094,7 @@ func substAny(t *Type, types *[]*Type) *Type {
|
|||||||
t = (*types)[0]
|
t = (*types)[0]
|
||||||
*types = (*types)[1:]
|
*types = (*types)[1:]
|
||||||
|
|
||||||
case TPTR32, TPTR64, TCHAN, TARRAY, TFIELD:
|
case TPTR32, TPTR64, TCHAN, TARRAY:
|
||||||
elem := substAny(t.Type, types)
|
elem := substAny(t.Type, types)
|
||||||
if elem != t.Type {
|
if elem != t.Type {
|
||||||
t = t.Copy()
|
t = t.Copy()
|
||||||
@ -1133,24 +1131,35 @@ func substAny(t *Type, types *[]*Type) *Type {
|
|||||||
|
|
||||||
case TSTRUCT:
|
case TSTRUCT:
|
||||||
// nfs only has to be big enough for the builtin functions.
|
// nfs only has to be big enough for the builtin functions.
|
||||||
var nfs [8]*Type
|
var nfs [8]*Field
|
||||||
fields := t.FieldSlice()
|
fields := t.FieldSlice()
|
||||||
changed := false
|
changed := false
|
||||||
for i, f := range fields {
|
for i, f := range fields {
|
||||||
nf := substAny(f, types)
|
nft := substAny(f.Type, types)
|
||||||
if nf != f {
|
if nft != f.Type {
|
||||||
if !changed {
|
nfs[i] = f.Copy()
|
||||||
for j := 0; j < i; j++ {
|
nfs[i].Type = nft
|
||||||
nfs[j] = fields[j].Copy()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
changed = true
|
changed = true
|
||||||
} else if changed {
|
|
||||||
nf = f.Copy()
|
|
||||||
}
|
}
|
||||||
nfs[i] = nf
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if changed {
|
if changed {
|
||||||
|
// Above we've initialized nfs with copied fields
|
||||||
|
// whenever the field type changed. However, because
|
||||||
|
// we keep fields in a linked list, we can only safely
|
||||||
|
// share the unmodified tail of the list. We need to
|
||||||
|
// copy the rest.
|
||||||
|
tail := true
|
||||||
|
for i := len(fields) - 1; i >= 0; i-- {
|
||||||
|
if nfs[i] != nil {
|
||||||
|
tail = false
|
||||||
|
} else if tail {
|
||||||
|
nfs[i] = fields[i]
|
||||||
|
} else {
|
||||||
|
nfs[i] = fields[i].Copy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
t = t.Copy()
|
t = t.Copy()
|
||||||
t.SetFields(nfs[:len(fields)])
|
t.SetFields(nfs[:len(fields)])
|
||||||
}
|
}
|
||||||
@ -1540,7 +1549,7 @@ func Setmaxarg(t *Type, extra int32) {
|
|||||||
// A Dlist stores a pointer to a TFIELD Type embedded within
|
// A Dlist stores a pointer to a TFIELD Type embedded within
|
||||||
// a TSTRUCT or TINTER Type.
|
// a TSTRUCT or TINTER Type.
|
||||||
type Dlist struct {
|
type Dlist struct {
|
||||||
field *Type
|
field *Field
|
||||||
}
|
}
|
||||||
|
|
||||||
// dotlist is used by adddot1 to record the path of embedded fields
|
// dotlist is used by adddot1 to record the path of embedded fields
|
||||||
@ -1551,7 +1560,7 @@ var dotlist = make([]Dlist, 10)
|
|||||||
// lookdot0 returns the number of fields or methods named s associated
|
// lookdot0 returns the number of fields or methods named s associated
|
||||||
// with Type t. If exactly one exists, it will be returned in *save
|
// with Type t. If exactly one exists, it will be returned in *save
|
||||||
// (if save is not nil).
|
// (if save is not nil).
|
||||||
func lookdot0(s *Sym, t *Type, save **Type, ignorecase bool) int {
|
func lookdot0(s *Sym, t *Type, save **Field, ignorecase bool) int {
|
||||||
u := t
|
u := t
|
||||||
if Isptr[u.Etype] {
|
if Isptr[u.Etype] {
|
||||||
u = u.Type
|
u = u.Type
|
||||||
@ -1590,7 +1599,7 @@ func lookdot0(s *Sym, t *Type, save **Type, ignorecase bool) int {
|
|||||||
// in reverse order. If none exist, more will indicate whether t contains any
|
// in reverse order. If none exist, more will indicate whether t contains any
|
||||||
// embedded fields at depth d, so callers can decide whether to retry at
|
// embedded fields at depth d, so callers can decide whether to retry at
|
||||||
// a greater depth.
|
// a greater depth.
|
||||||
func adddot1(s *Sym, t *Type, d int, save **Type, ignorecase bool) (c int, more bool) {
|
func adddot1(s *Sym, t *Type, d int, save **Field, ignorecase bool) (c int, more bool) {
|
||||||
if t.Trecur != 0 {
|
if t.Trecur != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1644,7 +1653,7 @@ out:
|
|||||||
// a selection expression x.f, where x is of type t and f is the symbol s.
|
// a selection expression x.f, where x is of type t and f is the symbol s.
|
||||||
// If no such path exists, dotpath returns nil.
|
// If no such path exists, dotpath returns nil.
|
||||||
// If there are multiple shortest paths to the same depth, ambig is true.
|
// If there are multiple shortest paths to the same depth, ambig is true.
|
||||||
func dotpath(s *Sym, t *Type, save **Type, ignorecase bool) (path []Dlist, ambig bool) {
|
func dotpath(s *Sym, t *Type, save **Field, ignorecase bool) (path []Dlist, ambig bool) {
|
||||||
// The embedding of types within structs imposes a tree structure onto
|
// The embedding of types within structs imposes a tree structure onto
|
||||||
// types: structs parent the types they embed, and types parent their
|
// types: structs parent the types they embed, and types parent their
|
||||||
// fields or methods. Our goal here is to find the shortest path to
|
// fields or methods. Our goal here is to find the shortest path to
|
||||||
@ -1713,7 +1722,7 @@ func adddot(n *Node) *Node {
|
|||||||
// with unique tasks and they return
|
// with unique tasks and they return
|
||||||
// the actual methods.
|
// the actual methods.
|
||||||
type Symlink struct {
|
type Symlink struct {
|
||||||
field *Type
|
field *Field
|
||||||
link *Symlink
|
link *Symlink
|
||||||
good bool
|
good bool
|
||||||
followptr bool
|
followptr bool
|
||||||
@ -1803,7 +1812,6 @@ func expandmeth(t *Type) {
|
|||||||
|
|
||||||
// mark top-level method symbols
|
// mark top-level method symbols
|
||||||
// so that expand1 doesn't consider them.
|
// so that expand1 doesn't consider them.
|
||||||
var f *Type
|
|
||||||
for f, it := IterMethods(t); f != nil; f = it.Next() {
|
for f, it := IterMethods(t); f != nil; f = it.Next() {
|
||||||
f.Sym.Flags |= SymUniq
|
f.Sym.Flags |= SymUniq
|
||||||
}
|
}
|
||||||
@ -1816,6 +1824,7 @@ func expandmeth(t *Type) {
|
|||||||
// check each method to be uniquely reachable
|
// check each method to be uniquely reachable
|
||||||
for sl := slist; sl != nil; sl = sl.link {
|
for sl := slist; sl != nil; sl = sl.link {
|
||||||
sl.field.Sym.Flags &^= SymUniq
|
sl.field.Sym.Flags &^= SymUniq
|
||||||
|
var f *Field
|
||||||
if path, _ := dotpath(sl.field.Sym, t, &f, false); path == nil {
|
if path, _ := dotpath(sl.field.Sym, t, &f, false); path == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -1894,7 +1903,7 @@ func structargs(tl *Type, mustname bool) []*Node {
|
|||||||
|
|
||||||
var genwrapper_linehistdone int = 0
|
var genwrapper_linehistdone int = 0
|
||||||
|
|
||||||
func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
|
func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) {
|
||||||
if false && Debug['r'] != 0 {
|
if false && Debug['r'] != 0 {
|
||||||
fmt.Printf("genwrapper rcvrtype=%v method=%v newnam=%v\n", rcvr, method, newnam)
|
fmt.Printf("genwrapper rcvrtype=%v method=%v newnam=%v\n", rcvr, method, newnam)
|
||||||
}
|
}
|
||||||
@ -2045,14 +2054,14 @@ func hashmem(t *Type) *Node {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func ifacelookdot(s *Sym, t *Type, followptr *bool, ignorecase bool) *Type {
|
func ifacelookdot(s *Sym, t *Type, followptr *bool, ignorecase bool) *Field {
|
||||||
*followptr = false
|
*followptr = false
|
||||||
|
|
||||||
if t == nil {
|
if t == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var m *Type
|
var m *Field
|
||||||
path, ambig := dotpath(s, t, &m, ignorecase)
|
path, ambig := dotpath(s, t, &m, ignorecase)
|
||||||
if path == nil {
|
if path == nil {
|
||||||
if ambig {
|
if ambig {
|
||||||
@ -2076,7 +2085,7 @@ func ifacelookdot(s *Sym, t *Type, followptr *bool, ignorecase bool) *Type {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func implements(t *Type, iface *Type, m **Type, samename **Type, ptr *int) bool {
|
func implements(t, iface *Type, m, samename **Field, ptr *int) bool {
|
||||||
t0 := t
|
t0 := t
|
||||||
if t == nil {
|
if t == nil {
|
||||||
return false
|
return false
|
||||||
@ -2114,16 +2123,13 @@ func implements(t *Type, iface *Type, m **Type, samename **Type, ptr *int) bool
|
|||||||
if t != nil {
|
if t != nil {
|
||||||
expandmeth(t)
|
expandmeth(t)
|
||||||
}
|
}
|
||||||
var tm *Type
|
|
||||||
var imtype *Type
|
|
||||||
var followptr bool
|
|
||||||
var rcvr *Type
|
|
||||||
for im, it := IterFields(iface); im != nil; im = it.Next() {
|
for im, it := IterFields(iface); im != nil; im = it.Next() {
|
||||||
if im.Broke {
|
if im.Broke {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
imtype = methodfunc(im.Type, nil)
|
imtype := methodfunc(im.Type, nil)
|
||||||
tm = ifacelookdot(im.Sym, t, &followptr, false)
|
var followptr bool
|
||||||
|
tm := ifacelookdot(im.Sym, t, &followptr, false)
|
||||||
if tm == nil || tm.Nointerface || !Eqtype(methodfunc(tm.Type, nil), imtype) {
|
if tm == nil || tm.Nointerface || !Eqtype(methodfunc(tm.Type, nil), imtype) {
|
||||||
if tm == nil {
|
if tm == nil {
|
||||||
tm = ifacelookdot(im.Sym, t, &followptr, true)
|
tm = ifacelookdot(im.Sym, t, &followptr, true)
|
||||||
@ -2136,7 +2142,7 @@ func implements(t *Type, iface *Type, m **Type, samename **Type, ptr *int) bool
|
|||||||
|
|
||||||
// if pointer receiver in method,
|
// if pointer receiver in method,
|
||||||
// the method does not exist for value types.
|
// the method does not exist for value types.
|
||||||
rcvr = tm.Type.Recv().Type
|
rcvr := tm.Type.Recv().Type
|
||||||
|
|
||||||
if Isptr[rcvr.Etype] && !Isptr[t0.Etype] && !followptr && !isifacemethod(tm.Type) {
|
if Isptr[rcvr.Etype] && !Isptr[t0.Etype] && !followptr && !isifacemethod(tm.Type) {
|
||||||
if false && Debug['r'] != 0 {
|
if false && Debug['r'] != 0 {
|
||||||
|
@ -146,7 +146,7 @@ func typecheckswitch(n *Node) {
|
|||||||
|
|
||||||
// type switch
|
// type switch
|
||||||
case Etype:
|
case Etype:
|
||||||
var missing, have *Type
|
var missing, have *Field
|
||||||
var ptr int
|
var ptr int
|
||||||
switch {
|
switch {
|
||||||
case n1.Op == OLITERAL && Istype(n1.Type, TNIL):
|
case n1.Op == OLITERAL && Istype(n1.Type, TNIL):
|
||||||
|
@ -146,7 +146,7 @@ type Param struct {
|
|||||||
Stackparam *Node // OPARAM node referring to stack copy of param
|
Stackparam *Node // OPARAM node referring to stack copy of param
|
||||||
|
|
||||||
// ONAME PPARAM
|
// ONAME PPARAM
|
||||||
Field *Type // TFIELD in arg struct
|
Field *Field // TFIELD in arg struct
|
||||||
|
|
||||||
// ONAME closure param with PPARAMREF
|
// ONAME closure param with PPARAMREF
|
||||||
Outer *Node // outer PPARAMREF in nested closure
|
Outer *Node // outer PPARAMREF in nested closure
|
||||||
|
@ -51,7 +51,6 @@ const (
|
|||||||
TMAP
|
TMAP
|
||||||
TINTER
|
TINTER
|
||||||
TFORW
|
TFORW
|
||||||
TFIELD
|
|
||||||
TANY
|
TANY
|
||||||
TSTRING
|
TSTRING
|
||||||
TUNSAFEPTR
|
TUNSAFEPTR
|
||||||
@ -103,17 +102,14 @@ var (
|
|||||||
// A Type represents a Go type.
|
// A Type represents a Go type.
|
||||||
type Type struct {
|
type Type struct {
|
||||||
Etype EType
|
Etype EType
|
||||||
Nointerface bool
|
|
||||||
Noalg bool
|
Noalg bool
|
||||||
Chan uint8
|
Chan uint8
|
||||||
Trecur uint8 // to detect loops
|
Trecur uint8 // to detect loops
|
||||||
Printed bool
|
Printed bool
|
||||||
Embedded uint8 // TFIELD embedded type
|
Funarg bool // on TSTRUCT and TFIELD
|
||||||
Funarg bool // on TSTRUCT and TFIELD
|
Local bool // created in this file
|
||||||
Local bool // created in this file
|
|
||||||
Deferwidth bool
|
Deferwidth bool
|
||||||
Broke bool // broken type definition.
|
Broke bool // broken type definition.
|
||||||
Isddd bool // TFIELD is ... argument
|
|
||||||
Align uint8
|
Align uint8
|
||||||
Haspointers uint8 // 0 unknown, 1 no, 2 yes
|
Haspointers uint8 // 0 unknown, 1 no, 2 yes
|
||||||
|
|
||||||
@ -127,8 +123,8 @@ type Type struct {
|
|||||||
Intuple int
|
Intuple int
|
||||||
Outnamed bool
|
Outnamed bool
|
||||||
|
|
||||||
Method *Type
|
Method *Field
|
||||||
Xmethod *Type
|
Xmethod *Field
|
||||||
|
|
||||||
Sym *Sym
|
Sym *Sym
|
||||||
Vargen int32 // unique name for OTYPE/ONAME
|
Vargen int32 // unique name for OTYPE/ONAME
|
||||||
@ -137,15 +133,13 @@ type Type struct {
|
|||||||
Argwid int64
|
Argwid int64
|
||||||
|
|
||||||
// most nodes
|
// most nodes
|
||||||
Type *Type // actual type for TFIELD, element type for TARRAY, TCHAN, TMAP, TPTRxx
|
Type *Type // element type for TARRAY, TCHAN, TMAP, TPTRxx
|
||||||
Width int64 // offset in TFIELD, width in all others
|
Width int64
|
||||||
|
|
||||||
// TSTRUCT
|
// TSTRUCT
|
||||||
Fields *Type // first struct field
|
Fields *Field // first struct field
|
||||||
|
|
||||||
// TFIELD
|
Down *Type // key type in TMAP; next struct in Funarg TSTRUCT
|
||||||
Down *Type // next struct field, also key type in TMAP
|
|
||||||
Note *string // literal string annotation
|
|
||||||
|
|
||||||
// TARRAY
|
// TARRAY
|
||||||
Bound int64 // negative is slice
|
Bound int64 // negative is slice
|
||||||
@ -163,6 +157,24 @@ type Type struct {
|
|||||||
Copyto []*Node
|
Copyto []*Node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A Field represents a field in a struct or a method in an interface or
|
||||||
|
// associated with a named type.
|
||||||
|
type Field struct {
|
||||||
|
Nointerface bool
|
||||||
|
Embedded uint8 // embedded field
|
||||||
|
Funarg bool
|
||||||
|
Broke bool // broken field definition
|
||||||
|
Isddd bool // field is ... argument
|
||||||
|
|
||||||
|
Sym *Sym
|
||||||
|
Nname *Node
|
||||||
|
|
||||||
|
Type *Type // field type
|
||||||
|
Width int64 // TODO(mdempsky): Rename to offset.
|
||||||
|
Note *string // literal string annotation
|
||||||
|
Down *Field // next struct field
|
||||||
|
}
|
||||||
|
|
||||||
// typ returns a new Type of the specified kind.
|
// typ returns a new Type of the specified kind.
|
||||||
func typ(et EType) *Type {
|
func typ(et EType) *Type {
|
||||||
t := &Type{
|
t := &Type{
|
||||||
@ -174,6 +186,12 @@ func typ(et EType) *Type {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newField() *Field {
|
||||||
|
return &Field{
|
||||||
|
Width: BADWIDTH,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Copy returns a shallow copy of the Type.
|
// Copy returns a shallow copy of the Type.
|
||||||
func (t *Type) Copy() *Type {
|
func (t *Type) Copy() *Type {
|
||||||
if t == nil {
|
if t == nil {
|
||||||
@ -187,15 +205,20 @@ func (t *Type) Copy() *Type {
|
|||||||
return &nt
|
return &nt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Field) Copy() *Field {
|
||||||
|
nf := *f
|
||||||
|
return &nf
|
||||||
|
}
|
||||||
|
|
||||||
// Iter provides an abstraction for iterating across struct fields and
|
// Iter provides an abstraction for iterating across struct fields and
|
||||||
// interface methods.
|
// interface methods.
|
||||||
type Iter struct {
|
type Iter struct {
|
||||||
x *Type
|
x *Field
|
||||||
}
|
}
|
||||||
|
|
||||||
// IterFields returns the first field or method in struct or interface type t
|
// IterFields returns the first field or method in struct or interface type t
|
||||||
// and an Iter value to continue iterating across the rest.
|
// and an Iter value to continue iterating across the rest.
|
||||||
func IterFields(t *Type) (*Type, Iter) {
|
func IterFields(t *Type) (*Field, Iter) {
|
||||||
if t.Etype != TSTRUCT && t.Etype != TINTER {
|
if t.Etype != TSTRUCT && t.Etype != TINTER {
|
||||||
Fatalf("IterFields: type %v does not have fields", t)
|
Fatalf("IterFields: type %v does not have fields", t)
|
||||||
}
|
}
|
||||||
@ -205,14 +228,14 @@ func IterFields(t *Type) (*Type, Iter) {
|
|||||||
// IterMethods returns the first method in type t's method set
|
// IterMethods returns the first method in type t's method set
|
||||||
// and an Iter value to continue iterating across the rest.
|
// and an Iter value to continue iterating across the rest.
|
||||||
// IterMethods does not include promoted methods.
|
// IterMethods does not include promoted methods.
|
||||||
func IterMethods(t *Type) (*Type, Iter) {
|
func IterMethods(t *Type) (*Field, Iter) {
|
||||||
// TODO(mdempsky): Validate t?
|
// TODO(mdempsky): Validate t?
|
||||||
return RawIter(t.Method)
|
return RawIter(t.Method)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IterAllMethods returns the first (possibly promoted) method in type t's
|
// IterAllMethods returns the first (possibly promoted) method in type t's
|
||||||
// method set and an Iter value to continue iterating across the rest.
|
// method set and an Iter value to continue iterating across the rest.
|
||||||
func IterAllMethods(t *Type) (*Type, Iter) {
|
func IterAllMethods(t *Type) (*Field, Iter) {
|
||||||
// TODO(mdempsky): Validate t?
|
// TODO(mdempsky): Validate t?
|
||||||
return RawIter(t.Xmethod)
|
return RawIter(t.Xmethod)
|
||||||
}
|
}
|
||||||
@ -220,23 +243,20 @@ func IterAllMethods(t *Type) (*Type, Iter) {
|
|||||||
// RawIter returns field t and an Iter value to continue iterating across
|
// RawIter returns field t and an Iter value to continue iterating across
|
||||||
// its successor fields. Most code should instead use one of the IterXXX
|
// its successor fields. Most code should instead use one of the IterXXX
|
||||||
// functions above.
|
// functions above.
|
||||||
func RawIter(t *Type) (*Type, Iter) {
|
func RawIter(t *Field) (*Field, Iter) {
|
||||||
i := Iter{x: t}
|
i := Iter{x: t}
|
||||||
f := i.Next()
|
f := i.Next()
|
||||||
return f, i
|
return f, i
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next field or method, if any.
|
// Next returns the next field or method, if any.
|
||||||
func (i *Iter) Next() *Type {
|
func (i *Iter) Next() *Field {
|
||||||
if i.x == nil {
|
if i.x == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
t := i.x
|
f := i.x
|
||||||
if t.Etype != TFIELD {
|
i.x = f.Down
|
||||||
Fatalf("Iter.Next: type %v is not a field", t)
|
return f
|
||||||
}
|
|
||||||
i.x = t.Down
|
|
||||||
return t
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) wantEtype(et EType) {
|
func (t *Type) wantEtype(et EType) {
|
||||||
@ -264,7 +284,7 @@ func (t *Type) Recvs() *Type { return *t.RecvsP() }
|
|||||||
func (t *Type) Params() *Type { return *t.ParamsP() }
|
func (t *Type) Params() *Type { return *t.ParamsP() }
|
||||||
func (t *Type) Results() *Type { return *t.ResultsP() }
|
func (t *Type) Results() *Type { return *t.ResultsP() }
|
||||||
|
|
||||||
func (t *Type) Recv() *Type { return t.Recvs().Field(0) }
|
func (t *Type) Recv() *Field { return t.Recvs().Field(0) }
|
||||||
|
|
||||||
// recvsParamsResults stores the accessor functions for a function Type's
|
// recvsParamsResults stores the accessor functions for a function Type's
|
||||||
// receiver, parameters, and result parameters, in that order.
|
// receiver, parameters, and result parameters, in that order.
|
||||||
@ -280,7 +300,7 @@ func (t *Type) Key() *Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Field returns the i'th field/method of struct/interface type t.
|
// Field returns the i'th field/method of struct/interface type t.
|
||||||
func (t *Type) Field(i int) *Type {
|
func (t *Type) Field(i int) *Field {
|
||||||
// TODO: store fields in a slice so we can
|
// TODO: store fields in a slice so we can
|
||||||
// look them up by index in constant time.
|
// look them up by index in constant time.
|
||||||
for f, it := IterFields(t); f != nil; f = it.Next() {
|
for f, it := IterFields(t); f != nil; f = it.Next() {
|
||||||
@ -301,8 +321,8 @@ func (t *Type) Field(i int) *Type {
|
|||||||
|
|
||||||
// FieldSlice returns a slice of containing all fields/methods of
|
// FieldSlice returns a slice of containing all fields/methods of
|
||||||
// struct/interface type t.
|
// struct/interface type t.
|
||||||
func (t *Type) FieldSlice() []*Type {
|
func (t *Type) FieldSlice() []*Field {
|
||||||
var s []*Type
|
var s []*Field
|
||||||
for f, it := IterFields(t); f != nil; f = it.Next() {
|
for f, it := IterFields(t); f != nil; f = it.Next() {
|
||||||
s = append(s, f)
|
s = append(s, f)
|
||||||
}
|
}
|
||||||
@ -310,11 +330,11 @@ func (t *Type) FieldSlice() []*Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetFields sets struct/interface type t's fields/methods to fields.
|
// SetFields sets struct/interface type t's fields/methods to fields.
|
||||||
func (t *Type) SetFields(fields []*Type) {
|
func (t *Type) SetFields(fields []*Field) {
|
||||||
if t.Etype != TSTRUCT && t.Etype != TINTER {
|
if t.Etype != TSTRUCT && t.Etype != TINTER {
|
||||||
Fatalf("SetFields: type %v does not have fields", t)
|
Fatalf("SetFields: type %v does not have fields", t)
|
||||||
}
|
}
|
||||||
var next *Type
|
var next *Field
|
||||||
for i := len(fields) - 1; i >= 0; i-- {
|
for i := len(fields) - 1; i >= 0; i-- {
|
||||||
fields[i].Down = next
|
fields[i].Down = next
|
||||||
next = fields[i]
|
next = fields[i]
|
||||||
@ -456,12 +476,14 @@ func (t *Type) cmp(x *Type) ssa.Cmp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch t.Etype {
|
switch t.Etype {
|
||||||
case TMAP, TFIELD:
|
case TMAP:
|
||||||
// No special cases for these two, they are handled
|
if c := t.Down.cmp(x.Down); c != ssa.CMPeq {
|
||||||
// by the general code after the switch.
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
case TPTR32, TPTR64:
|
case TPTR32, TPTR64:
|
||||||
return t.Type.cmp(x.Type)
|
// No special cases for these two, they are handled
|
||||||
|
// by the general code after the switch.
|
||||||
|
|
||||||
case TSTRUCT:
|
case TSTRUCT:
|
||||||
if t.Map == nil {
|
if t.Map == nil {
|
||||||
@ -545,9 +567,7 @@ func (t *Type) cmp(x *Type) ssa.Cmp {
|
|||||||
panic(e)
|
panic(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c := t.Down.cmp(x.Down); c != ssa.CMPeq {
|
// Common element type comparison for TARRAY, TCHAN, TMAP, TPTR32, and TPTR64.
|
||||||
return c
|
|
||||||
}
|
|
||||||
return t.Type.cmp(x.Type)
|
return t.Type.cmp(x.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -946,8 +946,7 @@ OpSwitch:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if n.Type != nil && n.Type.Etype != TINTER {
|
if n.Type != nil && n.Type.Etype != TINTER {
|
||||||
var have *Type
|
var missing, have *Field
|
||||||
var missing *Type
|
|
||||||
var ptr int
|
var ptr int
|
||||||
if !implements(n.Type, t, &missing, &have, &ptr) {
|
if !implements(n.Type, t, &missing, &have, &ptr) {
|
||||||
if have != nil && have.Sym == missing.Sym {
|
if have != nil && have.Sym == missing.Sym {
|
||||||
@ -2363,8 +2362,8 @@ func twoarg(n *Node) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func lookdot1(errnode *Node, s *Sym, t *Type, f *Type, dostrcmp int) *Type {
|
func lookdot1(errnode *Node, s *Sym, t *Type, f *Field, dostrcmp int) *Field {
|
||||||
var r *Type
|
var r *Field
|
||||||
for f, it := RawIter(f); f != nil; f = it.Next() {
|
for f, it := RawIter(f); f != nil; f = it.Next() {
|
||||||
if dostrcmp != 0 && f.Sym.Name == s.Name {
|
if dostrcmp != 0 && f.Sym.Name == s.Name {
|
||||||
return f
|
return f
|
||||||
@ -2410,14 +2409,13 @@ func looktypedot(n *Node, t *Type, dostrcmp int) bool {
|
|||||||
|
|
||||||
// Find the base type: methtype will fail if t
|
// Find the base type: methtype will fail if t
|
||||||
// is not of the form T or *T.
|
// is not of the form T or *T.
|
||||||
f2 := methtype(t, 0)
|
mt := methtype(t, 0)
|
||||||
|
if mt == nil {
|
||||||
if f2 == nil {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
expandmeth(f2)
|
expandmeth(mt)
|
||||||
f2 = lookdot1(n, s, f2, f2.Xmethod, dostrcmp)
|
f2 := lookdot1(n, s, mt, mt.Xmethod, dostrcmp)
|
||||||
if f2 == nil {
|
if f2 == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -2449,24 +2447,24 @@ type typeSym struct {
|
|||||||
|
|
||||||
// dotField maps (*Type, *Sym) pairs to the corresponding struct field (*Type with Etype==TFIELD).
|
// dotField maps (*Type, *Sym) pairs to the corresponding struct field (*Type with Etype==TFIELD).
|
||||||
// It is a cache for use during usefield in walk.go, only enabled when field tracking.
|
// It is a cache for use during usefield in walk.go, only enabled when field tracking.
|
||||||
var dotField = map[typeSym]*Type{}
|
var dotField = map[typeSym]*Field{}
|
||||||
|
|
||||||
func lookdot(n *Node, t *Type, dostrcmp int) *Type {
|
func lookdot(n *Node, t *Type, dostrcmp int) *Field {
|
||||||
s := n.Right.Sym
|
s := n.Right.Sym
|
||||||
|
|
||||||
dowidth(t)
|
dowidth(t)
|
||||||
var f1 *Type
|
var f1 *Field
|
||||||
if t.Etype == TSTRUCT || t.Etype == TINTER {
|
if t.Etype == TSTRUCT || t.Etype == TINTER {
|
||||||
f1 = lookdot1(n, s, t, t.Fields, dostrcmp)
|
f1 = lookdot1(n, s, t, t.Fields, dostrcmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
var f2 *Type
|
var f2 *Field
|
||||||
if n.Left.Type == t || n.Left.Type.Sym == nil {
|
if n.Left.Type == t || n.Left.Type.Sym == nil {
|
||||||
f2 = methtype(t, 0)
|
mt := methtype(t, 0)
|
||||||
if f2 != nil {
|
if mt != nil {
|
||||||
// Use f2->method, not f2->xmethod: adddot has
|
// Use f2->method, not f2->xmethod: adddot has
|
||||||
// already inserted all the necessary embedded dots.
|
// already inserted all the necessary embedded dots.
|
||||||
f2 = lookdot1(n, s, f2, f2.Method, dostrcmp)
|
f2 = lookdot1(n, s, mt, mt.Method, dostrcmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,18 +370,18 @@ func lexinit1() {
|
|||||||
|
|
||||||
rcvr := typ(TSTRUCT)
|
rcvr := typ(TSTRUCT)
|
||||||
rcvr.Funarg = true
|
rcvr.Funarg = true
|
||||||
field := typ(TFIELD)
|
field := newField()
|
||||||
field.Type = Ptrto(typ(TSTRUCT))
|
field.Type = Ptrto(typ(TSTRUCT))
|
||||||
rcvr.SetFields([]*Type{field})
|
rcvr.SetFields([]*Field{field})
|
||||||
|
|
||||||
in := typ(TSTRUCT)
|
in := typ(TSTRUCT)
|
||||||
in.Funarg = true
|
in.Funarg = true
|
||||||
|
|
||||||
out := typ(TSTRUCT)
|
out := typ(TSTRUCT)
|
||||||
out.Funarg = true
|
out.Funarg = true
|
||||||
field = typ(TFIELD)
|
field = newField()
|
||||||
field.Type = Types[TSTRING]
|
field.Type = Types[TSTRING]
|
||||||
out.SetFields([]*Type{field})
|
out.SetFields([]*Field{field})
|
||||||
|
|
||||||
f := typ(TFUNC)
|
f := typ(TFUNC)
|
||||||
*f.RecvsP() = rcvr
|
*f.RecvsP() = rcvr
|
||||||
@ -393,10 +393,10 @@ func lexinit1() {
|
|||||||
f.Outtuple = 1
|
f.Outtuple = 1
|
||||||
|
|
||||||
t := typ(TINTER)
|
t := typ(TINTER)
|
||||||
field = typ(TFIELD)
|
field = newField()
|
||||||
field.Sym = Lookup("Error")
|
field.Sym = Lookup("Error")
|
||||||
field.Type = f
|
field.Type = f
|
||||||
t.SetFields([]*Type{field})
|
t.SetFields([]*Field{field})
|
||||||
|
|
||||||
// error type
|
// error type
|
||||||
s := Pkglookup("error", builtinpkg)
|
s := Pkglookup("error", builtinpkg)
|
||||||
|
@ -1752,7 +1752,7 @@ func ascompatet(op Op, nl Nodes, nr *Type, fp int, init *Nodes) []*Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// package all the arguments that match a ... T parameter into a []T.
|
// package all the arguments that match a ... T parameter into a []T.
|
||||||
func mkdotargslice(lr0, nn []*Node, l *Type, fp int, init *Nodes, ddd *Node) []*Node {
|
func mkdotargslice(lr0, nn []*Node, l *Field, fp int, init *Nodes, ddd *Node) []*Node {
|
||||||
esc := uint16(EscUnknown)
|
esc := uint16(EscUnknown)
|
||||||
if ddd != nil {
|
if ddd != nil {
|
||||||
esc = ddd.Esc
|
esc = ddd.Esc
|
||||||
@ -1792,7 +1792,7 @@ func dumptypes(nl *Type, what string) string {
|
|||||||
if s != "" {
|
if s != "" {
|
||||||
s += ", "
|
s += ", "
|
||||||
}
|
}
|
||||||
s += Tconv(l, 0)
|
s += Fldconv(l, 0)
|
||||||
}
|
}
|
||||||
if s == "" {
|
if s == "" {
|
||||||
s = fmt.Sprintf("[no arguments %s]", what)
|
s = fmt.Sprintf("[no arguments %s]", what)
|
||||||
@ -3774,7 +3774,7 @@ func usemethod(n *Node) {
|
|||||||
}
|
}
|
||||||
p0 := t.Params().Field(0)
|
p0 := t.Params().Field(0)
|
||||||
res0 := t.Results().Field(0)
|
res0 := t.Results().Field(0)
|
||||||
var res1 *Type
|
var res1 *Field
|
||||||
if countfield(t.Results()) == 2 {
|
if countfield(t.Results()) == 2 {
|
||||||
res1 = t.Results().Field(1)
|
res1 = t.Results().Field(1)
|
||||||
}
|
}
|
||||||
@ -3791,7 +3791,7 @@ func usemethod(n *Node) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if Tconv(res0, 0) != "reflect.Method" {
|
if Tconv(res0.Type, 0) != "reflect.Method" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user