From b536adbfba6d13e141ba65cda77d69e4ce7e5177 Mon Sep 17 00:00:00 2001 From: Luuk van Dijk Date: Sat, 8 Oct 2011 19:37:06 +0200 Subject: [PATCH] gc: changes to export format in preparation for inlining. string literals used as package qualifiers are now prefixed with '@' which obviates the need for the extra ':' before tags. R=rsc, gri, lvd CC=golang-dev https://golang.org/cl/5129057 --- src/cmd/gc/builtin.c.boot | 208 ++++++++++++++++----------------- src/cmd/gc/esc.c | 8 +- src/cmd/gc/export.c | 2 +- src/cmd/gc/gen.c | 2 +- src/cmd/gc/go.h | 9 +- src/cmd/gc/go.y | 45 +++---- src/cmd/gc/lex.c | 1 + src/cmd/gc/print.c | 161 +++++++++++++++++++++++-- src/cmd/gc/subr.c | 200 ++++++++++++++----------------- src/lib9/fmt/fmtprint.c | 26 ++--- src/lib9/fmt/fmtvprint.c | 28 ++--- src/pkg/go/types/gcimporter.go | 120 +++++++++++-------- test/ddd1.go | 4 +- test/escape2.go | 204 ++++++++++++++++---------------- 14 files changed, 563 insertions(+), 455 deletions(-) diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot index 190c560089d..67379813403 100644 --- a/src/cmd/gc/builtin.c.boot +++ b/src/cmd/gc/builtin.c.boot @@ -1,114 +1,114 @@ char *runtimeimport = "package runtime\n" "import runtime \"runtime\"\n" - "func \"\".new (? int32) *any\n" - "func \"\".panicindex ()\n" - "func \"\".panicslice ()\n" - "func \"\".throwreturn ()\n" - "func \"\".throwinit ()\n" - "func \"\".panicwrap (? string, ? string, ? string)\n" - "func \"\".panic (? interface { })\n" - "func \"\".recover (? *int32) interface { }\n" - "func \"\".printbool (? bool)\n" - "func \"\".printfloat (? float64)\n" - "func \"\".printint (? int64)\n" - "func \"\".printuint (? uint64)\n" - "func \"\".printcomplex (? complex128)\n" - "func \"\".printstring (? string)\n" - "func \"\".printpointer (? any)\n" - "func \"\".printiface (? any)\n" - "func \"\".printeface (? any)\n" - "func \"\".printslice (? any)\n" - "func \"\".printnl ()\n" - "func \"\".printsp ()\n" - "func \"\".goprintf ()\n" - "func \"\".concatstring ()\n" - "func \"\".append ()\n" - "func \"\".appendslice (typ *uint8, x any, y []any) any\n" - "func \"\".cmpstring (? string, ? string) int\n" - "func \"\".slicestring (? string, ? int, ? int) string\n" - "func \"\".slicestring1 (? string, ? int) string\n" - "func \"\".intstring (? int64) string\n" - "func \"\".slicebytetostring (? []uint8) string\n" - "func \"\".sliceinttostring (? []int) string\n" - "func \"\".stringtoslicebyte (? string) []uint8\n" - "func \"\".stringtosliceint (? string) []int\n" - "func \"\".stringiter (? string, ? int) int\n" - "func \"\".stringiter2 (? string, ? int) (retk int, retv int)\n" - "func \"\".slicecopy (to any, fr any, wid uint32) int\n" - "func \"\".slicestringcopy (to any, fr any) int\n" - "func \"\".convI2E (elem any) any\n" - "func \"\".convI2I (typ *uint8, elem any) any\n" - "func \"\".convT2E (typ *uint8, elem any) any\n" - "func \"\".convT2I (typ *uint8, typ2 *uint8, elem any) any\n" - "func \"\".assertE2E (typ *uint8, iface any) any\n" - "func \"\".assertE2E2 (typ *uint8, iface any) (ret any, ok bool)\n" - "func \"\".assertE2I (typ *uint8, iface any) any\n" - "func \"\".assertE2I2 (typ *uint8, iface any) (ret any, ok bool)\n" - "func \"\".assertE2T (typ *uint8, iface any) any\n" - "func \"\".assertE2T2 (typ *uint8, iface any) (ret any, ok bool)\n" - "func \"\".assertI2E (typ *uint8, iface any) any\n" - "func \"\".assertI2E2 (typ *uint8, iface any) (ret any, ok bool)\n" - "func \"\".assertI2I (typ *uint8, iface any) any\n" - "func \"\".assertI2I2 (typ *uint8, iface any) (ret any, ok bool)\n" - "func \"\".assertI2T (typ *uint8, iface any) any\n" - "func \"\".assertI2T2 (typ *uint8, iface any) (ret any, ok bool)\n" - "func \"\".ifaceeq (i1 any, i2 any) bool\n" - "func \"\".efaceeq (i1 any, i2 any) bool\n" - "func \"\".ifacethash (i1 any) uint32\n" - "func \"\".efacethash (i1 any) uint32\n" - "func \"\".makemap (mapType *uint8, hint int64) map[any] any\n" - "func \"\".mapaccess1 (mapType *uint8, hmap map[any] any, key any) any\n" - "func \"\".mapaccess2 (mapType *uint8, hmap map[any] any, key any) (val any, pres bool)\n" - "func \"\".mapassign1 (mapType *uint8, hmap map[any] any, key any, val any)\n" - "func \"\".mapassign2 (mapType *uint8, hmap map[any] any, key any, val any, pres bool)\n" - "func \"\".mapiterinit (mapType *uint8, hmap map[any] any, hiter *any)\n" - "func \"\".mapiternext (hiter *any)\n" - "func \"\".mapiter1 (hiter *any) any\n" - "func \"\".mapiter2 (hiter *any) (key any, val any)\n" - "func \"\".makechan (chanType *uint8, hint int64) chan any\n" - "func \"\".chanrecv1 (chanType *uint8, hchan <-chan any) any\n" - "func \"\".chanrecv2 (chanType *uint8, hchan <-chan any) (elem any, received bool)\n" - "func \"\".chansend1 (chanType *uint8, hchan chan<- any, elem any)\n" - "func \"\".closechan (hchan any)\n" - "func \"\".selectnbsend (chanType *uint8, hchan chan<- any, elem any) bool\n" - "func \"\".selectnbrecv (chanType *uint8, elem *any, hchan <-chan any) bool\n" - "func \"\".selectnbrecv2 (chanType *uint8, elem *any, received *bool, hchan <-chan any) bool\n" - "func \"\".newselect (size int) *uint8\n" - "func \"\".selectsend (sel *uint8, hchan chan<- any, elem *any) bool\n" - "func \"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) bool\n" - "func \"\".selectrecv2 (sel *uint8, hchan <-chan any, elem *any, received *bool) bool\n" - "func \"\".selectdefault (sel *uint8) bool\n" - "func \"\".selectgo (sel *uint8)\n" - "func \"\".block ()\n" - "func \"\".makeslice (typ *uint8, nel int64, cap int64) []any\n" - "func \"\".growslice (typ *uint8, old []any, n int64) []any\n" - "func \"\".sliceslice1 (old []any, lb uint64, width uint64) []any\n" - "func \"\".sliceslice (old []any, lb uint64, hb uint64, width uint64) []any\n" - "func \"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n" - "func \"\".closure ()\n" - "func \"\".int64div (? int64, ? int64) int64\n" - "func \"\".uint64div (? uint64, ? uint64) uint64\n" - "func \"\".int64mod (? int64, ? int64) int64\n" - "func \"\".uint64mod (? uint64, ? uint64) uint64\n" - "func \"\".float64toint64 (? float64) int64\n" - "func \"\".float64touint64 (? float64) uint64\n" - "func \"\".int64tofloat64 (? int64) float64\n" - "func \"\".uint64tofloat64 (? uint64) float64\n" - "func \"\".complex128div (num complex128, den complex128) complex128\n" + "func @\"\".new (? int32) *any\n" + "func @\"\".panicindex ()\n" + "func @\"\".panicslice ()\n" + "func @\"\".throwreturn ()\n" + "func @\"\".throwinit ()\n" + "func @\"\".panicwrap (? string, ? string, ? string)\n" + "func @\"\".panic (? interface { })\n" + "func @\"\".recover (? *int32) interface { }\n" + "func @\"\".printbool (? bool)\n" + "func @\"\".printfloat (? float64)\n" + "func @\"\".printint (? int64)\n" + "func @\"\".printuint (? uint64)\n" + "func @\"\".printcomplex (? complex128)\n" + "func @\"\".printstring (? string)\n" + "func @\"\".printpointer (? any)\n" + "func @\"\".printiface (? any)\n" + "func @\"\".printeface (? any)\n" + "func @\"\".printslice (? any)\n" + "func @\"\".printnl ()\n" + "func @\"\".printsp ()\n" + "func @\"\".goprintf ()\n" + "func @\"\".concatstring ()\n" + "func @\"\".append ()\n" + "func @\"\".appendslice (typ *uint8, x any, y []any) any\n" + "func @\"\".cmpstring (? string, ? string) int\n" + "func @\"\".slicestring (? string, ? int, ? int) string\n" + "func @\"\".slicestring1 (? string, ? int) string\n" + "func @\"\".intstring (? int64) string\n" + "func @\"\".slicebytetostring (? []uint8) string\n" + "func @\"\".sliceinttostring (? []int) string\n" + "func @\"\".stringtoslicebyte (? string) []uint8\n" + "func @\"\".stringtosliceint (? string) []int\n" + "func @\"\".stringiter (? string, ? int) int\n" + "func @\"\".stringiter2 (? string, ? int) (retk int, retv int)\n" + "func @\"\".slicecopy (to any, fr any, wid uint32) int\n" + "func @\"\".slicestringcopy (to any, fr any) int\n" + "func @\"\".convI2E (elem any) any\n" + "func @\"\".convI2I (typ *uint8, elem any) any\n" + "func @\"\".convT2E (typ *uint8, elem any) any\n" + "func @\"\".convT2I (typ *uint8, typ2 *uint8, elem any) any\n" + "func @\"\".assertE2E (typ *uint8, iface any) any\n" + "func @\"\".assertE2E2 (typ *uint8, iface any) (ret any, ok bool)\n" + "func @\"\".assertE2I (typ *uint8, iface any) any\n" + "func @\"\".assertE2I2 (typ *uint8, iface any) (ret any, ok bool)\n" + "func @\"\".assertE2T (typ *uint8, iface any) any\n" + "func @\"\".assertE2T2 (typ *uint8, iface any) (ret any, ok bool)\n" + "func @\"\".assertI2E (typ *uint8, iface any) any\n" + "func @\"\".assertI2E2 (typ *uint8, iface any) (ret any, ok bool)\n" + "func @\"\".assertI2I (typ *uint8, iface any) any\n" + "func @\"\".assertI2I2 (typ *uint8, iface any) (ret any, ok bool)\n" + "func @\"\".assertI2T (typ *uint8, iface any) any\n" + "func @\"\".assertI2T2 (typ *uint8, iface any) (ret any, ok bool)\n" + "func @\"\".ifaceeq (i1 any, i2 any) bool\n" + "func @\"\".efaceeq (i1 any, i2 any) bool\n" + "func @\"\".ifacethash (i1 any) uint32\n" + "func @\"\".efacethash (i1 any) uint32\n" + "func @\"\".makemap (mapType *uint8, hint int64) map[any] any\n" + "func @\"\".mapaccess1 (mapType *uint8, hmap map[any] any, key any) any\n" + "func @\"\".mapaccess2 (mapType *uint8, hmap map[any] any, key any) (val any, pres bool)\n" + "func @\"\".mapassign1 (mapType *uint8, hmap map[any] any, key any, val any)\n" + "func @\"\".mapassign2 (mapType *uint8, hmap map[any] any, key any, val any, pres bool)\n" + "func @\"\".mapiterinit (mapType *uint8, hmap map[any] any, hiter *any)\n" + "func @\"\".mapiternext (hiter *any)\n" + "func @\"\".mapiter1 (hiter *any) any\n" + "func @\"\".mapiter2 (hiter *any) (key any, val any)\n" + "func @\"\".makechan (chanType *uint8, hint int64) chan any\n" + "func @\"\".chanrecv1 (chanType *uint8, hchan <-chan any) any\n" + "func @\"\".chanrecv2 (chanType *uint8, hchan <-chan any) (elem any, received bool)\n" + "func @\"\".chansend1 (chanType *uint8, hchan chan<- any, elem any)\n" + "func @\"\".closechan (hchan any)\n" + "func @\"\".selectnbsend (chanType *uint8, hchan chan<- any, elem any) bool\n" + "func @\"\".selectnbrecv (chanType *uint8, elem *any, hchan <-chan any) bool\n" + "func @\"\".selectnbrecv2 (chanType *uint8, elem *any, received *bool, hchan <-chan any) bool\n" + "func @\"\".newselect (size int) *uint8\n" + "func @\"\".selectsend (sel *uint8, hchan chan<- any, elem *any) bool\n" + "func @\"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) bool\n" + "func @\"\".selectrecv2 (sel *uint8, hchan <-chan any, elem *any, received *bool) bool\n" + "func @\"\".selectdefault (sel *uint8) bool\n" + "func @\"\".selectgo (sel *uint8)\n" + "func @\"\".block ()\n" + "func @\"\".makeslice (typ *uint8, nel int64, cap int64) []any\n" + "func @\"\".growslice (typ *uint8, old []any, n int64) []any\n" + "func @\"\".sliceslice1 (old []any, lb uint64, width uint64) []any\n" + "func @\"\".sliceslice (old []any, lb uint64, hb uint64, width uint64) []any\n" + "func @\"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n" + "func @\"\".closure ()\n" + "func @\"\".int64div (? int64, ? int64) int64\n" + "func @\"\".uint64div (? uint64, ? uint64) uint64\n" + "func @\"\".int64mod (? int64, ? int64) int64\n" + "func @\"\".uint64mod (? uint64, ? uint64) uint64\n" + "func @\"\".float64toint64 (? float64) int64\n" + "func @\"\".float64touint64 (? float64) uint64\n" + "func @\"\".int64tofloat64 (? int64) float64\n" + "func @\"\".uint64tofloat64 (? uint64) float64\n" + "func @\"\".complex128div (num complex128, den complex128) complex128\n" "\n" "$$\n"; char *unsafeimport = "package unsafe\n" "import runtime \"runtime\"\n" - "type \"\".Pointer uintptr\n" - "func \"\".Offsetof (? any) uintptr\n" - "func \"\".Sizeof (? any) uintptr\n" - "func \"\".Alignof (? any) uintptr\n" - "func \"\".Typeof (i interface { }) interface { }\n" - "func \"\".Reflect (i interface { }) (typ interface { }, addr \"\".Pointer)\n" - "func \"\".Unreflect (typ interface { }, addr \"\".Pointer) interface { }\n" - "func \"\".New (typ interface { }) \"\".Pointer\n" - "func \"\".NewArray (typ interface { }, n int) \"\".Pointer\n" + "type @\"\".Pointer uintptr\n" + "func @\"\".Offsetof (? any) uintptr\n" + "func @\"\".Sizeof (? any) uintptr\n" + "func @\"\".Alignof (? any) uintptr\n" + "func @\"\".Typeof (i interface { }) interface { }\n" + "func @\"\".Reflect (i interface { }) (typ interface { }, addr @\"\".Pointer)\n" + "func @\"\".Unreflect (typ interface { }, addr @\"\".Pointer) interface { }\n" + "func @\"\".New (typ interface { }) @\"\".Pointer\n" + "func @\"\".NewArray (typ interface { }, n int) @\"\".Pointer\n" "\n" "$$\n"; diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c index cd1f9770e19..c158afc4c55 100644 --- a/src/cmd/gc/esc.c +++ b/src/cmd/gc/esc.c @@ -88,7 +88,7 @@ escapes(void) if(debug['m']) { for(l=noesc; l; l=l->next) if(l->n->esc == EscNone) - warnl(l->n->lineno, "%S %#N does not escape", + warnl(l->n->lineno, "%S %#hN does not escape", (l->n->curfn && l->n->curfn->nname) ? l->n->curfn->nname->sym : S, l->n); } @@ -643,7 +643,7 @@ escwalk(int level, Node *dst, Node *src) if(src->class == PPARAM && leaks && src->esc == EscNone) { src->esc = EscScope; if(debug['m']) - warnl(src->lineno, "leaking param: %hN", src); + warnl(src->lineno, "leaking param: %#hN", src); } break; @@ -652,7 +652,7 @@ escwalk(int level, Node *dst, Node *src) src->esc = EscHeap; addrescapes(src->left); if(debug['m']) - warnl(src->lineno, "%#N escapes to heap", src); + warnl(src->lineno, "%#hN escapes to heap", src); } escwalk(level-1, dst, src->left); break; @@ -671,7 +671,7 @@ escwalk(int level, Node *dst, Node *src) if(leaks) { src->esc = EscHeap; if(debug['m']) - warnl(src->lineno, "%#N escapes to heap", src); + warnl(src->lineno, "%#hN escapes to heap", src); } break; diff --git a/src/cmd/gc/export.c b/src/cmd/gc/export.c index 421afda8b40..58b1154ed71 100644 --- a/src/cmd/gc/export.c +++ b/src/cmd/gc/export.c @@ -7,7 +7,7 @@ #include "go.h" #include "y.tab.h" -static void dumpsym(Sym*); +static void dumpsym(Sym*); static void dumpexporttype(Sym*); static void dumpexportvar(Sym*); static void dumpexportconst(Sym*); diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c index cd6d9aaf5a4..eeee3c4be34 100644 --- a/src/cmd/gc/gen.c +++ b/src/cmd/gc/gen.c @@ -94,7 +94,7 @@ addrescapes(Node *n) if(!debug['s']) n->esc = EscHeap; if(debug['m']) - print("%L: moved to heap: %hN\n", n->lineno, n); + print("%L: moved to heap: %#hN\n", n->lineno, n); curfn = oldfn; break; } diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index f72799420b1..2d4ba31c7e4 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -375,10 +375,10 @@ EXTERN Sym* dclstack; struct Pkg { - char* name; - Strlit* path; + char* name; // package name + Strlit* path; // string literal used in import statement Sym* pathsym; - char* prefix; + char* prefix; // escaped path for use in symbol table Pkg* link; char exported; // import line written in export data char direct; // imported directly @@ -1130,7 +1130,7 @@ int Nconv(Fmt *fp); int Oconv(Fmt *fp); int Sconv(Fmt *fp); int Tconv(Fmt *fp); -int Tpretty(Fmt *fp, Type *t); +int Vconv(Fmt *fp); int Zconv(Fmt *fp); Node* adddot(Node *n); int adddot1(Sym *s, Type *t, int d, Type **save, int ignorecase); @@ -1348,5 +1348,6 @@ void zname(Biobuf *b, Sym *s, int t); #pragma varargck type "lS" Sym* #pragma varargck type "T" Type* #pragma varargck type "lT" Type* +#pragma varargck type "V" Val* #pragma varargck type "Y" char* #pragma varargck type "Z" Strlit* diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y index 0c007f5f0b4..63cff8655c0 100644 --- a/src/cmd/gc/go.y +++ b/src/cmd/gc/go.y @@ -78,8 +78,6 @@ static void fixlbrace(int); %type indcl interfacetype structtype ptrtype %type recvchantype non_recvchantype othertype fnret_type fntype -%type hidden_tag - %type hidden_importsym hidden_pkg_importsym %type hidden_constant hidden_literal hidden_dcl @@ -993,6 +991,16 @@ onew_name: sym: LNAME +| hidden_importsym + +hidden_importsym: + '@' LLITERAL '.' LNAME + { + if($2.u.sval->len == 0) + $$ = pkglookup($4->name, importpkg); + else + $$ = pkglookup($4->name, mkpkg($2.u.sval)); + } name: sym %prec NotParen @@ -1826,12 +1834,12 @@ hidden_opt_sym: } hidden_dcl: - hidden_opt_sym hidden_type hidden_tag + hidden_opt_sym hidden_type oliteral { $$ = nod(ODCLFIELD, $1, typenod($2)); $$->val = $3; } -| hidden_opt_sym LDDD hidden_type hidden_tag +| hidden_opt_sym LDDD hidden_type oliteral { Type *t; @@ -1844,12 +1852,12 @@ hidden_dcl: } hidden_structdcl: - sym hidden_type hidden_tag + sym hidden_type oliteral { $$ = nod(ODCLFIELD, newname($1), typenod($2)); $$->val = $3; } -| '?' hidden_type hidden_tag +| '?' hidden_type oliteral { Sym *s; @@ -1863,24 +1871,11 @@ hidden_structdcl: $$->val = $3; } -hidden_tag: - { - $$.ctype = CTxxx; - } -| ':' LLITERAL // extra colon avoids conflict with "" looking like beginning of "".typename - { - $$ = $2; - } - hidden_interfacedcl: sym '(' ohidden_funarg_list ')' ohidden_funres { $$ = nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5))); } -| hidden_importsym '(' ohidden_funarg_list ')' ohidden_funres - { - $$ = nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5))); - } ohidden_funres: { @@ -1931,18 +1926,6 @@ hidden_constant: $$ = nodcplxlit($2->val, $4->val); } -hidden_importsym: - LLITERAL '.' sym - { - Pkg *p; - - if($1.u.sval->len == 0) - p = importpkg; - else - p = mkpkg($1.u.sval); - $$ = pkglookup($3->name, p); - } - hidden_pkg_importsym: hidden_importsym { diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c index 0290fb13145..54970dc8f48 100644 --- a/src/cmd/gc/lex.c +++ b/src/cmd/gc/lex.c @@ -198,6 +198,7 @@ main(int argc, char *argv[]) fmtinstall('J', Jconv); // all the node flags fmtinstall('S', Sconv); // sym pointer fmtinstall('T', Tconv); // type pointer + fmtinstall('V', Vconv); // Val pointer fmtinstall('N', Nconv); // node pointer fmtinstall('Z', Zconv); // escaped string fmtinstall('L', Lconv); // line number diff --git a/src/cmd/gc/print.c b/src/cmd/gc/print.c index 37e3e7ac054..e270259509c 100644 --- a/src/cmd/gc/print.c +++ b/src/cmd/gc/print.c @@ -21,11 +21,22 @@ exprlistfmt(Fmt *f, NodeList *l) } } +void +stmtlistfmt(Fmt *f, NodeList *l) +{ + for(; l; l=l->next) { + fmtprint(f, " %#N", l->n); + if(l->next) + fmtprint(f, ";"); + } +} + void exprfmt(Fmt *f, Node *n, int prec) { int nprec; char *p; + NodeList *l; nprec = 0; if(n == nil) { @@ -107,6 +118,7 @@ exprfmt(Fmt *f, Node *n, int prec) case OGE: case OGT: case ONE: + case OCMPSTR: nprec = 4; break; @@ -269,6 +281,8 @@ exprfmt(Fmt *f, Node *n, int prec) break; case OADD: + case OADDSTR: + case OAND: case OANDAND: case OANDNOT: case ODIV: @@ -292,6 +306,12 @@ exprfmt(Fmt *f, Node *n, int prec) exprfmt(f, n->right, nprec+1); break; + case OCMPSTR: + exprfmt(f, n->left, nprec); + fmtprint(f, " %#O ", n->etype); + exprfmt(f, n->right, nprec+1); + break; + case OADDR: case OCOM: case OIND: @@ -306,7 +326,13 @@ exprfmt(Fmt *f, Node *n, int prec) break; case OCLOSURE: - fmtprint(f, "func literal"); + if(f->flags & FmtShort) { + fmtprint(f, "func literal", n->type); + } else { + fmtprint(f, "func %hhT {", n->type); + stmtlistfmt(f, n->nbody); + fmtprint(f, " }"); + } break; case OCOMPLIT: @@ -314,18 +340,18 @@ exprfmt(Fmt *f, Node *n, int prec) break; case OARRAYLIT: - if(isslice(n->type)) - fmtprint(f, "slice literal"); - else - fmtprint(f, "array literal"); - break; - case OMAPLIT: - fmtprint(f, "map literal"); - break; - case OSTRUCTLIT: - fmtprint(f, "struct literal"); + if(f->flags & FmtShort) { + fmtprint(f, "%#hhT literal", n->type); + } else { + fmtprint(f, "%#hhT{", n->type); + for (l=n->list; l; l=l->next) { + fmtprint(f, " %#N:%#N", l->n->left, l->n->right); + if (l->next) fmtprint(f, ","); + } + fmtprint(f, " }"); + } break; case OXDOT: @@ -479,6 +505,119 @@ exprfmt(Fmt *f, Node *n, int prec) case ODEFER: fmtprint(f, "defer %#N", n->left); break; + + case OIF: + if (n->ninit && n->ninit->next) { + fmtprint(f, "{"); + stmtlistfmt(f, n->ninit); + fmtprint(f, "; "); + } + fmtstrcpy(f, "if "); + if (n->ninit && !n->ninit->next) + fmtprint(f, "%#N; ", n->ninit->n); + fmtprint(f, "%#N {", n->ntest); + stmtlistfmt(f, n->nbody); + if (n->nelse) { + fmtprint(f, "} else {"); + stmtlistfmt(f, n->nelse); + } + fmtprint(f, "}"); + if (n->ninit && n->ninit->next) + fmtprint(f, "}"); + break; + + case OFOR: + if (n->ninit && n->ninit->next) { + fmtprint(f, "{"); + stmtlistfmt(f, n->ninit); + fmtprint(f, "; "); + } + fmtstrcpy(f, "for"); + if (n->ninit && !n->ninit->next) + fmtprint(f, " %#N;", n->ninit->n); + else if (n->ntest || n->nincr) + fmtstrcpy(f, " ;"); + if (n->ntest) + fmtprint(f, "%#N", n->ntest); + if (n->nincr) + fmtprint(f, "; %#N", n->nincr); + else if (n->ninit && !n->ninit->next) + fmtstrcpy(f, " ;"); + fmtstrcpy(f, " {"); + stmtlistfmt(f, n->nbody); + fmtprint(f, "}"); + if (n->ninit && n->ninit->next) + fmtprint(f, "}"); + break; + + case ORANGE: + if (n->ninit) { + fmtprint(f, "{"); + stmtlistfmt(f, n->ninit); + fmtprint(f, "; "); + } + fmtprint(f, "for "); + exprlistfmt(f, n->list); + fmtprint(f, " = range %#N {", n->right); + stmtlistfmt(f, n->nbody); + fmtprint(f, "}"); + if (n->ninit) + fmtprint(f, "}"); + break; + + case OSWITCH: + if (n->ninit && n->ninit->next) { + fmtprint(f, "{"); + stmtlistfmt(f, n->ninit); + fmtprint(f, "; "); + } + fmtstrcpy(f, "select"); + if (n->ninit && !n->ninit->next) + fmtprint(f, " %#N;", n->ninit->n); + if (n->ntest) + fmtprint(f, "%#N", n->ntest); + fmtstrcpy(f, " {"); + for(l=n->list; l; l=l->next) { + if (l->n->list) { + fmtprint(f, " case "); + exprlistfmt(f, l->n->list); + } else { + fmtprint(f, " default"); + } + fmtstrcpy(f, ":"); + stmtlistfmt(f, l->n->nbody); + if (l->next) + fmtprint(f, ";"); + } + fmtprint(f, " }"); + if (n->ninit) + fmtprint(f, "}"); + break; + + + case OSELECT: + if (n->ninit) { + fmtprint(f, "{"); + stmtlistfmt(f, n->ninit); + fmtprint(f, "; "); + } + fmtstrcpy(f, "select {"); + for(l=n->list; l; l=l->next) { + if (l->n->list) { + fmtprint(f, " case "); + exprlistfmt(f, l->n->list); + } else { + fmtprint(f, " default"); + } + fmtstrcpy(f, ":"); + stmtlistfmt(f, l->n->nbody); + if (l->next) + fmtprint(f, ";"); + } + fmtprint(f, " }"); + if (n->ninit) + fmtprint(f, "}"); + break; } if(prec > nprec) diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index b450b9b0e88..b584be8272e 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -768,6 +768,10 @@ dodump(Node *n, int dep) dodump(n->right, dep+1); break; + case OLITERAL: + print("%N v(%V)\n", n, &n->val); + break; + case OTYPE: print("%O %S type=%T\n", n->op, n->sym, n->type); if(n->type == T && n->ntype) { @@ -870,11 +874,38 @@ dump(char *s, Node *n) dodump(n, 1); } +int +Vconv(Fmt *fp) +{ + Val *v; + + v = va_arg(fp->args, Val*); + + switch(v->ctype) { + case CTINT: + return fmtprint(fp, "%B", v->u.xval); + case CTFLT: + return fmtprint(fp, "%g", mpgetflt(v->u.fval)); + case CTCPLX: + return fmtprint(fp, "(%g+%gi)", + mpgetflt(&v->u.cval->real), + mpgetflt(&v->u.cval->imag)); + case CTSTR: + return fmtprint(fp, "\"%Z\"", v->u.sval); + case CTBOOL: + return fmtprint(fp, "%d", v->u.bval); + case CTNIL: + return fmtprint(fp, "nil"); + } + return fmtprint(fp, "<%d>", v->ctype); +} + static char* goopnames[] = { [OADDR] = "&", [OADD] = "+", + [OADDSTR] = "+", [OANDAND] = "&&", [OANDNOT] = "&^", [OAND] = "&", @@ -1165,44 +1196,42 @@ Jconv(Fmt *fp) return 0; } +// Flags for %S +// 'h' FmtShort -> just print the name +// '#' FmtSharp -> qualify with package prefix or @"path", depending on global flag packagequotes. +// (automatic when global flag exporting is set) +// 'l' FmtLong -> qualify with package name or "path" (automatic when global flag +// longsymnames is set (by typehash) or sym is not in localpkg) int Sconv(Fmt *fp) { Sym *s; s = va_arg(fp->args, Sym*); - if(s == S) { - fmtstrcpy(fp, ""); - return 0; - } + if(s == S) + return fmtstrcpy(fp, ""); if(fp->flags & FmtShort) goto shrt; if(exporting || (fp->flags & FmtSharp)) { if(packagequotes) - fmtprint(fp, "\"%Z\"", s->pkg->path); + return fmtprint(fp, "@\"%Z\".%s", s->pkg->path, s->name); else - fmtprint(fp, "%s", s->pkg->prefix); - fmtprint(fp, ".%s", s->name); - return 0; + return fmtprint(fp, "%s.%s", s->pkg->prefix, s->name); } if(s->pkg && s->pkg != localpkg || longsymnames || (fp->flags & FmtLong)) { // This one is for the user. If the package name // was used by multiple packages, give the full // import path to disambiguate. - if(erroring && pkglookup(s->pkg->name, nil)->npkg > 1) { - fmtprint(fp, "\"%Z\".%s", s->pkg->path, s->name); - return 0; - } - fmtprint(fp, "%s.%s", s->pkg->name, s->name); - return 0; + if(erroring && pkglookup(s->pkg->name, nil)->npkg > 1) + return fmtprint(fp, "\"%Z\".%s", s->pkg->path, s->name); + return fmtprint(fp, "%s.%s", s->pkg->name, s->name); } shrt: - fmtstrcpy(fp, s->name); - return 0; + return fmtstrcpy(fp, s->name); } static char* @@ -1231,7 +1260,11 @@ basicnames[] = [TBLANK] = "blank", }; -int +// Global flag exporting +// Global flag noargnames +// 'h' FmtShort +// 'l' FmtLong +static int Tpretty(Fmt *fp, Type *t) { Type *t1; @@ -1255,9 +1288,7 @@ Tpretty(Fmt *fp, Type *t) fmtprint(fp, "%hS", s); else fmtprint(fp, "%S", s); - if(s->pkg != localpkg) - return 0; - if(t->vargen) + if(s->pkg == localpkg && t->vargen) fmtprint(fp, "ยท%d", t->vargen); return 0; } @@ -1401,8 +1432,6 @@ Tpretty(Fmt *fp, Type *t) fmtprint(fp, "%T", t->type); if(t->note) { fmtprint(fp, " "); - if(exporting) - fmtprint(fp, ":"); fmtprint(fp, "\"%Z\"", t->note); } return 0; @@ -1416,115 +1445,58 @@ Tpretty(Fmt *fp, Type *t) case TUNSAFEPTR: if(exporting) - return fmtprint(fp, "\"unsafe\".Pointer"); + return fmtprint(fp, "@\"unsafe\".Pointer"); return fmtprint(fp, "unsafe.Pointer"); + default: + if(exporting) + fatal("missing %E case during export", t->etype); + // Don't know how to handle - fall back to detailed prints. + return fmtprint(fp, "%E <%S> %T", t->etype, t->sym, t->type); } - // Don't know how to handle - fall back to detailed prints. + fatal("not reached"); return -1; } +// %T flags: +// '#' FmtSharp -> 'exporting' mode global flag, affects Tpretty and Sconv +// '-' FmtLeft -> 'noargnames' global flag, affects Tpretty +// 'h' FmtShort -> handled by Tpretty +// 'l' FmtLong -> handled by Tpretty int Tconv(Fmt *fp) { - Type *t, *t1; - int r, et, sharp, minus; - - sharp = (fp->flags & FmtSharp); - minus = (fp->flags & FmtLeft); - fp->flags &= ~(FmtSharp|FmtLeft); + Type *t; + int r,sharp, minus, sf; t = va_arg(fp->args, Type*); if(t == T) return fmtstrcpy(fp, ""); + if(t->trecur > 4) { + return fmtstrcpy(fp, "..."); + } + t->trecur++; - if(t->trecur > 5) { - fmtprint(fp, "..."); - goto out; - } - if(!debug['t']) { - if(sharp) - exporting++; - if(minus) - noargnames++; - r = Tpretty(fp, t); - if(sharp) - exporting--; - if(minus) - noargnames--; - if(r >= 0) { - t->trecur--; - return 0; - } - } + sharp = (fp->flags & FmtSharp); + minus = (fp->flags & FmtLeft); + sf = fp->flags; + fp->flags &= ~(FmtSharp|FmtLeft); - if(sharp || exporting) - fatal("missing %E case during export", t->etype); + if(sharp) + exporting++; + if(minus) + noargnames++; + r = Tpretty(fp, t); + if(sharp) + exporting--; + if(minus) + noargnames--; - et = t->etype; - fmtprint(fp, "%E ", et); - if(t->sym != S) - fmtprint(fp, "<%S>", t->sym); - - switch(et) { - default: - if(t->type != T) - fmtprint(fp, " %T", t->type); - break; - - case TFIELD: - fmtprint(fp, "%T", t->type); - break; - - case TFUNC: - if(fp->flags & FmtLong) - fmtprint(fp, "%d%d%d(%lT,%lT)%lT", - t->thistuple, t->intuple, t->outtuple, - t->type, t->type->down->down, t->type->down); - else - fmtprint(fp, "%d%d%d(%T,%T)%T", - t->thistuple, t->intuple, t->outtuple, - t->type, t->type->down->down, t->type->down); - break; - - case TINTER: - fmtprint(fp, "{"); - if(fp->flags & FmtLong) - for(t1=t->type; t1!=T; t1=t1->down) - fmtprint(fp, "%lT;", t1); - fmtprint(fp, "}"); - break; - - case TSTRUCT: - fmtprint(fp, "{"); - if(fp->flags & FmtLong) - for(t1=t->type; t1!=T; t1=t1->down) - fmtprint(fp, "%lT;", t1); - fmtprint(fp, "}"); - break; - - case TMAP: - fmtprint(fp, "[%T]%T", t->down, t->type); - break; - - case TARRAY: - if(t->bound >= 0) - fmtprint(fp, "[%d]%T", t->bound, t->type); - else - fmtprint(fp, "[]%T", t->type); - break; - - case TPTR32: - case TPTR64: - fmtprint(fp, "%T", t->type); - break; - } - -out: + fp->flags = sf; t->trecur--; - return 0; + return r; } int @@ -1541,11 +1513,11 @@ Nconv(Fmt *fp) if(fp->flags & FmtSign) { if(n->type == T) - fmtprint(fp, "%#N", n); + fmtprint(fp, "%#hN", n); else if(n->type->etype == TNIL) fmtprint(fp, "nil"); else - fmtprint(fp, "%#N (type %T)", n, n->type); + fmtprint(fp, "%#hN (type %T)", n, n->type); goto out; } diff --git a/src/lib9/fmt/fmtprint.c b/src/lib9/fmt/fmtprint.c index 8a29e6fafa5..6848ab4ebb8 100644 --- a/src/lib9/fmt/fmtprint.c +++ b/src/lib9/fmt/fmtprint.c @@ -21,31 +21,19 @@ #include "fmtdef.h" /* - * format a string into the output buffer - * designed for formats which themselves call fmt, - * but ignore any width flags + * Format a string into the output buffer. + * Designed for formats which themselves call fmt. + * Flags, precision and width are preserved. */ int fmtprint(Fmt *f, char *fmt, ...) { - va_list va; int n; + va_list va; - f->flags = 0; - f->width = 0; - f->prec = 0; - VA_COPY(va, f->args); - VA_END(f->args); - va_start(f->args, fmt); - n = dofmt(f, fmt); - va_end(f->args); - f->flags = 0; - f->width = 0; - f->prec = 0; - VA_COPY(f->args,va); - VA_END(va); - if(n >= 0) - return 0; + va_start(va, fmt); + n = fmtvprint(f, fmt, va); + va_end(va); return n; } diff --git a/src/lib9/fmt/fmtvprint.c b/src/lib9/fmt/fmtvprint.c index 6acd37a51df..f18d27bbad0 100644 --- a/src/lib9/fmt/fmtvprint.c +++ b/src/lib9/fmt/fmtvprint.c @@ -22,31 +22,31 @@ /* - * format a string into the output buffer - * designed for formats which themselves call fmt, - * but ignore any width flags + * Format a string into the output buffer. + * Designed for formats which themselves call fmt. + * Flags, precision and width are preserved. */ int fmtvprint(Fmt *f, char *fmt, va_list args) { va_list va; - int n; + int n, w, p; + unsigned long fl; - f->flags = 0; - f->width = 0; - f->prec = 0; - VA_COPY(va,f->args); + w = f->width; + p = f->prec; + fl = f->flags; + VA_COPY(va, f->args); VA_END(f->args); - VA_COPY(f->args,args); + VA_COPY(f->args, args); n = dofmt(f, fmt); - f->flags = 0; - f->width = 0; - f->prec = 0; VA_END(f->args); - VA_COPY(f->args,va); + VA_COPY(f->args, va); VA_END(va); + f->width = w; + f->prec = p; + f->flags = fl; if(n >= 0) return 0; return n; } - diff --git a/src/pkg/go/types/gcimporter.go b/src/pkg/go/types/gcimporter.go index 6ab1806b643..fe90f910807 100644 --- a/src/pkg/go/types/gcimporter.go +++ b/src/pkg/go/types/gcimporter.go @@ -142,6 +142,34 @@ func GcImporter(imports map[string]*ast.Object, path string) (pkg *ast.Object, e return } +// Declare inserts a named object of the given kind in scope. +func (p *gcParser) declare(scope *ast.Scope, kind ast.ObjKind, name string) *ast.Object { + // a type may have been declared before - if it exists + // already in the respective package scope, return that + // type + if kind == ast.Typ { + if obj := scope.Lookup(name); obj != nil { + assert(obj.Kind == ast.Typ) + return obj + } + } + + // any other object must be a newly declared object - + // create it and insert it into the package scope + obj := ast.NewObj(kind, name) + if scope.Insert(obj) != nil { + p.errorf("already declared: %v %s", kind, obj.Name) + } + + // a new type object is a named type and may be referred + // to before the underlying type is known - set it up + if kind == ast.Typ { + obj.Type = &Name{Obj: obj} + } + + return obj +} + // ---------------------------------------------------------------------------- // Error handling @@ -245,38 +273,14 @@ func (p *gcParser) parseDotIdent() string { return ident } -// ExportedName = ImportPath "." dotIdentifier . +// ExportedName = "@" ImportPath "." dotIdentifier . // -func (p *gcParser) parseExportedName(kind ast.ObjKind) *ast.Object { +func (p *gcParser) parseExportedName() (*ast.Object, string) { + p.expect('@') pkg := p.parsePkgId() p.expect('.') name := p.parseDotIdent() - - // a type may have been declared before - if it exists - // already in the respective package scope, return that - // type - scope := pkg.Data.(*ast.Scope) - if kind == ast.Typ { - if obj := scope.Lookup(name); obj != nil { - assert(obj.Kind == ast.Typ) - return obj - } - } - - // any other object must be a newly declared object - - // create it and insert it into the package scope - obj := ast.NewObj(kind, name) - if scope.Insert(obj) != nil { - p.errorf("already declared: %s", obj.Name) - } - - // a new type object is a named type and may be referred - // to before the underlying type is known - set it up - if kind == ast.Typ { - obj.Type = &Name{Obj: obj} - } - - return obj + return pkg, name } // ---------------------------------------------------------------------------- @@ -333,7 +337,7 @@ func (p *gcParser) parseName() (name string) { return } -// Field = Name Type [ ":" string_lit ] . +// Field = Name Type [ string_lit ] . // func (p *gcParser) parseField() (fld *ast.Object, tag string) { name := p.parseName() @@ -344,8 +348,7 @@ func (p *gcParser) parseField() (fld *ast.Object, tag string) { p.errorf("anonymous field expected") } } - if p.tok == ':' { - p.next() + if p.tok == scanner.String { tag = p.expect(scanner.String) } fld = ast.NewObj(ast.Var, name) @@ -380,7 +383,7 @@ func (p *gcParser) parseStructType() Type { return &Struct{Fields: fields, Tags: tags} } -// Parameter = ( identifier | "?" ) [ "..." ] Type [ ":" string_lit ] . +// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] . // func (p *gcParser) parseParameter() (par *ast.Object, isVariadic bool) { name := p.parseName() @@ -393,8 +396,7 @@ func (p *gcParser) parseParameter() (par *ast.Object, isVariadic bool) { } ptyp := p.parseType() // ignore argument tag - if p.tok == ':' { - p.next() + if p.tok == scanner.String { p.expect(scanner.String) } par = ast.NewObj(ast.Var, name) @@ -439,7 +441,7 @@ func (p *gcParser) parseSignature() *Func { // optional result type var results []*ast.Object switch p.tok { - case scanner.Ident, scanner.String, '[', '*', '<': + case scanner.Ident, '[', '*', '<', '@': // single, unnamed result result := ast.NewObj(ast.Var, "_") result.Type = p.parseType() @@ -456,16 +458,13 @@ func (p *gcParser) parseSignature() *Func { return &Func{Params: params, Results: results, IsVariadic: isVariadic} } -// MethodSpec = identifier Signature . +// MethodSpec = ( identifier | ExportedName ) Signature . // func (p *gcParser) parseMethodSpec() *ast.Object { if p.tok == scanner.Ident { p.expect(scanner.Ident) } else { - // TODO(gri) should this be parseExportedName here? - p.parsePkgId() - p.expect('.') - p.parseDotIdent() + p.parseExportedName() } p.parseSignature() @@ -547,9 +546,10 @@ func (p *gcParser) parseType() Type { case "chan": return p.parseChanType() } - case scanner.String: + case '@': // TypeName - return p.parseExportedName(ast.Typ).Type.(Type) + pkg, name := p.parseExportedName() + return p.declare(pkg.Data.(*ast.Scope), ast.Typ, name).Type.(Type) case '[': p.next() // look ahead if p.tok == ']' { @@ -643,7 +643,8 @@ func (p *gcParser) parseNumber() Const { // func (p *gcParser) parseConstDecl() { p.expectKeyword("const") - obj := p.parseExportedName(ast.Con) + pkg, name := p.parseExportedName() + obj := p.declare(pkg.Data.(*ast.Scope), ast.Con, name) var x Const var typ Type if p.tok != '=' { @@ -693,7 +694,8 @@ func (p *gcParser) parseConstDecl() { // func (p *gcParser) parseTypeDecl() { p.expectKeyword("type") - obj := p.parseExportedName(ast.Typ) + pkg, name := p.parseExportedName() + obj := p.declare(pkg.Data.(*ast.Scope), ast.Typ, name) // The type object may have been imported before and thus already // have a type associated with it. We still need to parse the type @@ -712,20 +714,39 @@ func (p *gcParser) parseTypeDecl() { // func (p *gcParser) parseVarDecl() { p.expectKeyword("var") - obj := p.parseExportedName(ast.Var) + pkg, name := p.parseExportedName() + obj := p.declare(pkg.Data.(*ast.Scope), ast.Var, name) obj.Type = p.parseType() } -// FuncDecl = "func" ExportedName Signature . +// FuncBody = "{" ... "}" . +// +func (p *gcParser) parseFuncBody() { + p.expect('{') + for i := 1; i > 0; p.next() { + switch p.tok { + case '{': + i++ + case '}': + i-- + } + } +} + +// FuncDecl = "func" ExportedName Signature [ FuncBody ] . // func (p *gcParser) parseFuncDecl() { // "func" already consumed - obj := p.parseExportedName(ast.Fun) + pkg, name := p.parseExportedName() + obj := p.declare(pkg.Data.(*ast.Scope), ast.Fun, name) obj.Type = p.parseSignature() + if p.tok == '{' { + p.parseFuncBody() + } } // MethodDecl = "func" Receiver identifier Signature . -// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" . +// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" [ FuncBody ]. // func (p *gcParser) parseMethodDecl() { // "func" already consumed @@ -734,6 +755,9 @@ func (p *gcParser) parseMethodDecl() { p.expect(')') p.expect(scanner.Ident) p.parseSignature() + if p.tok == '{' { + p.parseFuncBody() + } } // Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" . diff --git a/test/ddd1.go b/test/ddd1.go index 83e32de7b6b..6d84248e5e8 100644 --- a/test/ddd1.go +++ b/test/ddd1.go @@ -15,8 +15,8 @@ var ( _ = sum() _ = sum(1.0, 2.0) _ = sum(1.5) // ERROR "integer" - _ = sum("hello") // ERROR "string.*as type int|incompatible" - _ = sum([]int{1}) // ERROR "slice literal.*as type int|incompatible" + _ = sum("hello") // ERROR ".hello. .type string. as type int|incompatible" + _ = sum([]int{1}) // ERROR "\[\]int literal.*as type int|incompatible" ) type T []T diff --git a/test/escape2.go b/test/escape2.go index dbe0c690651..7366a53c7f8 100644 --- a/test/escape2.go +++ b/test/escape2.go @@ -10,21 +10,21 @@ import "unsafe" var gxx *int -func foo1(x int) { // ERROR "moved to heap: NAME-x" +func foo1(x int) { // ERROR "moved to heap: x" gxx = &x // ERROR "&x escapes to heap" } -func foo2(yy *int) { // ERROR "leaking param: NAME-yy" +func foo2(yy *int) { // ERROR "leaking param: yy" gxx = yy } -func foo3(x int) *int { // ERROR "moved to heap: NAME-x" +func foo3(x int) *int { // ERROR "moved to heap: x" return &x // ERROR "&x escapes to heap" } type T *T -func foo3b(t T) { // ERROR "leaking param: NAME-t" +func foo3b(t T) { // ERROR "leaking param: t" *t = t } @@ -38,7 +38,7 @@ func foo5(xx **int, yy *int) { // ERROR "xx does not escape" "yy does not escape xx = &yy // ERROR "&yy does not escape" } -func foo6(xx **int, yy *int) { // ERROR "xx does not escape" "leaking param: NAME-yy" +func foo6(xx **int, yy *int) { // ERROR "xx does not escape" "leaking param: yy" *xx = yy } @@ -51,7 +51,7 @@ func foo8(xx, yy *int) int { // ERROR "xx does not escape" "yy does not escape" return *xx } -func foo9(xx, yy *int) *int { // ERROR "leaking param: NAME-xx" "leaking param: NAME-yy" +func foo9(xx, yy *int) *int { // ERROR "leaking param: xx" "leaking param: yy" xx = yy return xx } @@ -70,7 +70,7 @@ func foo11() int { var xxx **int -func foo12(yyy **int) { // ERROR "leaking param: NAME-yyy" +func foo12(yyy **int) { // ERROR "leaking param: yyy" xxx = yyy } @@ -82,11 +82,11 @@ func foo14(yyy **int) { // ERROR "yyy does not escape" **xxx = **yyy } -func foo15(yy *int) { // ERROR "moved to heap: NAME-yy" +func foo15(yy *int) { // ERROR "moved to heap: yy" xxx = &yy // ERROR "&yy escapes to heap" } -func foo16(yy *int) { // ERROR "leaking param: NAME-yy" +func foo16(yy *int) { // ERROR "leaking param: yy" *xxx = yy } @@ -94,7 +94,7 @@ func foo17(yy *int) { // ERROR "yy does not escape" **xxx = *yy } -func foo18(y int) { // ERROR "moved to heap: "NAME-y" +func foo18(y int) { // ERROR "moved to heap: "y" *xxx = &y // ERROR "&y escapes to heap" } @@ -108,15 +108,15 @@ type Bar struct { } func NewBar() *Bar { - return &Bar{42, nil} // ERROR "&struct literal escapes to heap" + return &Bar{42, nil} // ERROR "&Bar literal escapes to heap" } -func NewBarp(x *int) *Bar { // ERROR "leaking param: NAME-x" - return &Bar{42, x} // ERROR "&struct literal escapes to heap" +func NewBarp(x *int) *Bar { // ERROR "leaking param: x" + return &Bar{42, x} // ERROR "&Bar literal escapes to heap" } func NewBarp2(x *int) *Bar { // ERROR "x does not escape" - return &Bar{*x, nil} // ERROR "&struct literal escapes to heap" + return &Bar{*x, nil} // ERROR "&Bar literal escapes to heap" } func (b *Bar) NoLeak() int { // ERROR "b does not escape" @@ -127,7 +127,7 @@ func (b *Bar) AlsoNoLeak() *int { // ERROR "b does not escape" return b.ii } -func goLeak(b *Bar) { // ERROR "leaking param: NAME-b" +func goLeak(b *Bar) { // ERROR "leaking param: b" go b.NoLeak() } @@ -137,14 +137,14 @@ type Bar2 struct { } func NewBar2() *Bar2 { - return &Bar2{[12]int{42}, nil} // ERROR "&struct literal escapes to heap" + return &Bar2{[12]int{42}, nil} // ERROR "&Bar2 literal escapes to heap" } func (b *Bar2) NoLeak() int { // ERROR "b does not escape" return b.i[0] } -func (b *Bar2) Leak() []int { // ERROR "leaking param: NAME-b" +func (b *Bar2) Leak() []int { // ERROR "leaking param: b" return b.i[:] // ERROR "&b.i escapes to heap" } @@ -152,18 +152,18 @@ func (b *Bar2) AlsoNoLeak() []int { // ERROR "b does not escape" return b.ii[0:1] } -func (b *Bar2) LeakSelf() { // ERROR "leaking param: NAME-b" +func (b *Bar2) LeakSelf() { // ERROR "leaking param: b" b.ii = b.i[0:4] // ERROR "&b.i escapes to heap" } -func (b *Bar2) LeakSelf2() { // ERROR "leaking param: NAME-b" +func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b" var buf []int buf = b.i[0:] // ERROR "&b.i escapes to heap" b.ii = buf } func foo21() func() int { - x := 42 // ERROR "moved to heap: NAME-x" + x := 42 // ERROR "moved to heap: x" return func() int { // ERROR "func literal escapes to heap" return x // ERROR "&x escapes to heap" } @@ -176,21 +176,21 @@ func foo22() int { }() } -func foo23(x int) func() int { // ERROR "moved to heap: NAME-x" +func foo23(x int) func() int { // ERROR "moved to heap: x" return func() int { // ERROR "func literal escapes to heap" return x // ERROR "&x escapes to heap" } } -func foo23a(x int) func() int { // ERROR "moved to heap: NAME-x" +func foo23a(x int) func() int { // ERROR "moved to heap: x" f := func() int { // ERROR "func literal escapes to heap" return x // ERROR "&x escapes to heap" } return f } -func foo23b(x int) *(func() int) { // ERROR "moved to heap: NAME-x" - f := func() int { return x } // ERROR "moved to heap: NAME-f" "func literal escapes to heap" "&x escapes to heap" +func foo23b(x int) *(func() int) { // ERROR "moved to heap: x" + f := func() int { return x } // ERROR "moved to heap: f" "func literal escapes to heap" "&x escapes to heap" return &f // ERROR "&f escapes to heap" } @@ -202,7 +202,7 @@ func foo24(x int) int { var x *int -func fooleak(xx *int) int { // ERROR "leaking param: NAME-xx" +func fooleak(xx *int) int { // ERROR "leaking param: xx" x = xx return *x } @@ -211,7 +211,7 @@ func foonoleak(xx *int) int { // ERROR "xx does not escape" return *x + *xx } -func foo31(x int) int { // ERROR "moved to heap: NAME-x" +func foo31(x int) int { // ERROR "moved to heap: x" return fooleak(&x) // ERROR "&x escapes to heap" } @@ -227,7 +227,7 @@ type Foo struct { var F Foo var pf *Foo -func (f *Foo) fooleak() { // ERROR "leaking param: NAME-f" +func (f *Foo) fooleak() { // ERROR "leaking param: f" pf = f } @@ -235,7 +235,7 @@ func (f *Foo) foonoleak() { // ERROR "f does not escape" F.x = f.x } -func (f *Foo) Leak() { // ERROR "leaking param: NAME-f" +func (f *Foo) Leak() { // ERROR "leaking param: f" f.fooleak() } @@ -243,19 +243,19 @@ func (f *Foo) NoLeak() { // ERROR "f does not escape" f.foonoleak() } -func foo41(x int) { // ERROR "moved to heap: NAME-x" +func foo41(x int) { // ERROR "moved to heap: x" F.xx = &x // ERROR "&x escapes to heap" } -func (f *Foo) foo42(x int) { // ERROR "f does not escape" "moved to heap: NAME-x" +func (f *Foo) foo42(x int) { // ERROR "f does not escape" "moved to heap: x" f.xx = &x // ERROR "&x escapes to heap" } -func foo43(f *Foo, x int) { // ERROR "f does not escape" "moved to heap: NAME-x" +func foo43(f *Foo, x int) { // ERROR "f does not escape" "moved to heap: x" f.xx = &x // ERROR "&x escapes to heap" } -func foo44(yy *int) { // ERROR "leaking param: NAME-yy" +func foo44(yy *int) { // ERROR "leaking param: yy" F.xx = yy } @@ -267,31 +267,31 @@ func (f *Foo) foo46() { // ERROR "f does not escape" F.xx = f.xx } -func (f *Foo) foo47() { // ERROR "leaking param: NAME-f" +func (f *Foo) foo47() { // ERROR "leaking param: f" f.xx = &f.x // ERROR "&f.x escapes to heap" } var ptrSlice []*int -func foo50(i *int) { // ERROR "leaking param: NAME-i" +func foo50(i *int) { // ERROR "leaking param: i" ptrSlice[0] = i } var ptrMap map[*int]*int -func foo51(i *int) { // ERROR "leaking param: NAME-i" +func foo51(i *int) { // ERROR "leaking param: i" ptrMap[i] = i } -func indaddr1(x int) *int { // ERROR "moved to heap: NAME-x" +func indaddr1(x int) *int { // ERROR "moved to heap: x" return &x // ERROR "&x escapes to heap" } -func indaddr2(x *int) *int { // ERROR "leaking param: NAME-x" +func indaddr2(x *int) *int { // ERROR "leaking param: x" return *&x // ERROR "&x does not escape" } -func indaddr3(x *int32) *int { // ERROR "leaking param: NAME-x" +func indaddr3(x *int32) *int { // ERROR "leaking param: x" return *(**int)(unsafe.Pointer(&x)) // ERROR "&x does not escape" } @@ -314,26 +314,26 @@ func Float64frombits(b uint64) float64 { } // contrast with -func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: NAME-f" +func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f" return (*uint64)(unsafe.Pointer(&f)) // ERROR "&f escapes to heap" } -func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: NAME-f" +func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f" return (*uint64)(unsafe.Pointer(f)) } -func typesw(i interface{}) *int { // ERROR "leaking param: NAME-i" +func typesw(i interface{}) *int { // ERROR "leaking param: i" switch val := i.(type) { case *int: return val case *int8: - v := int(*val) // ERROR "moved to heap: NAME-v" + v := int(*val) // ERROR "moved to heap: v" return &v // ERROR "&v escapes to heap" } return nil } -func exprsw(i *int) *int { // ERROR "leaking param: NAME-i" +func exprsw(i *int) *int { // ERROR "leaking param: i" switch j := i; *j + 110 { case 12: return j @@ -345,7 +345,7 @@ func exprsw(i *int) *int { // ERROR "leaking param: NAME-i" } // assigning to an array element is like assigning to the array -func foo60(i *int) *int { // ERROR "leaking param: NAME-i" +func foo60(i *int) *int { // ERROR "leaking param: i" var a [12]*int a[0] = i return a[1] @@ -358,7 +358,7 @@ func foo60a(i *int) *int { // ERROR "i does not escape" } // assigning to a struct field is like assigning to the struct -func foo61(i *int) *int { // ERROR "leaking param: NAME-i" +func foo61(i *int) *int { // ERROR "leaking param: i" type S struct { a, b *int } @@ -379,7 +379,7 @@ func foo61a(i *int) *int { // ERROR "i does not escape" // assigning to a struct field is like assigning to the struct but // here this subtlety is lost, since s.a counts as an assignment to a // track-losing dereference. -func foo62(i *int) *int { // ERROR "leaking param: NAME-i" +func foo62(i *int) *int { // ERROR "leaking param: i" type S struct { a, b *int } @@ -395,11 +395,11 @@ type M interface { func foo63(m M) { // ERROR "m does not escape" } -func foo64(m M) { // ERROR "leaking param: NAME-m" +func foo64(m M) { // ERROR "leaking param: m" m.M() } -func foo64b(m M) { // ERROR "leaking param: NAME-m" +func foo64b(m M) { // ERROR "leaking param: m" defer m.M() } @@ -413,7 +413,7 @@ func foo65() { } func foo66() { - var mv MV // ERROR "moved to heap: NAME-mv" + var mv MV // ERROR "moved to heap: mv" foo64(&mv) // ERROR "&mv escapes to heap" } @@ -427,22 +427,22 @@ func foo68() { foo64(mv) // escapes but it's an int so irrelevant } -func foo69(m M) { // ERROR "leaking param: NAME-m" +func foo69(m M) { // ERROR "leaking param: m" foo64(m) } -func foo70(mv1 *MV, m M) { // ERROR "leaking param: NAME-mv1" "leaking param: NAME-m" +func foo70(mv1 *MV, m M) { // ERROR "leaking param: mv1" "leaking param: m" m = mv1 foo64(m) } -func foo71(x *int) []*int { // ERROR "leaking param: NAME-x" +func foo71(x *int) []*int { // ERROR "leaking param: x" var y []*int y = append(y, x) return y } -func foo71a(x int) []*int { // ERROR "moved to heap: NAME-x" +func foo71a(x int) []*int { // ERROR "moved to heap: x" var y []*int y = append(y, &x) // ERROR "&x escapes to heap" return y @@ -455,7 +455,7 @@ func foo72() { } func foo72aa() [10]*int { - var x int // ERROR "moved to heap: NAME-x" + var x int // ERROR "moved to heap: x" var y [10]*int y[0] = &x // ERROR "&x escapes to heap" return y @@ -465,7 +465,7 @@ func foo72a() { var y [10]*int for i := 0; i < 10; i++ { // escapes its scope - x := i // ERROR "moved to heap: NAME-x" + x := i // ERROR "moved to heap: x" y[i] = &x // ERROR "&x escapes to heap" } return @@ -474,7 +474,7 @@ func foo72a() { func foo72b() [10]*int { var y [10]*int for i := 0; i < 10; i++ { - x := i // ERROR "moved to heap: NAME-x" + x := i // ERROR "moved to heap: x" y[i] = &x // ERROR "&x escapes to heap" } return y @@ -482,9 +482,9 @@ func foo72b() [10]*int { // issue 2145 func foo73() { - s := []int{3, 2, 1} // ERROR "slice literal does not escape" + s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape" for _, v := range s { - vv := v // ERROR "moved to heap: NAME-vv" + vv := v // ERROR "moved to heap: vv" // actually just escapes its scope defer func() { // ERROR "func literal escapes to heap" println(vv) // ERROR "&vv escapes to heap" @@ -493,9 +493,9 @@ func foo73() { } func foo74() { - s := []int{3, 2, 1} // ERROR "slice literal does not escape" + s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape" for _, v := range s { - vv := v // ERROR "moved to heap: NAME-vv" + vv := v // ERROR "moved to heap: vv" // actually just escapes its scope fn := func() { // ERROR "func literal escapes to heap" println(vv) // ERROR "&vv escapes to heap" @@ -504,15 +504,15 @@ func foo74() { } } -func myprint(y *int, x ...interface{}) *int { // ERROR "x does not escape" "leaking param: NAME-y" +func myprint(y *int, x ...interface{}) *int { // ERROR "x does not escape" "leaking param: y" return y } -func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "y does not escape" "leaking param: NAME-x" +func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "y does not escape" "leaking param: x" return &x[0] // ERROR "&x.0. escapes to heap" } -func foo75(z *int) { // ERROR "leaking param: NAME-z" +func foo75(z *int) { // ERROR "leaking param: z" myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" } @@ -520,11 +520,11 @@ func foo75a(z *int) { // ERROR "z does not escape" myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap" } -func foo76(z *int) { // ERROR "leaking param: NAME-z" +func foo76(z *int) { // ERROR "leaking param: z" myprint(nil, z) // ERROR "[.][.][.] argument does not escape" } -func foo76a(z *int) { // ERROR "leaking param: NAME-z" +func foo76a(z *int) { // ERROR "leaking param: z" myprint1(nil, z) // ERROR "[.][.][.] argument escapes to heap" } @@ -561,15 +561,15 @@ func foo77(z []interface{}) { // ERROR "z does not escape" myprint(nil, z...) // z does not escape } -func foo77a(z []interface{}) { // ERROR "leaking param: NAME-z" +func foo77a(z []interface{}) { // ERROR "leaking param: z" myprint1(nil, z...) } -func foo78(z int) *int { // ERROR "moved to heap: NAME-z" +func foo78(z int) *int { // ERROR "moved to heap: z" return &z // ERROR "&z escapes to heap" } -func foo78a(z int) *int { // ERROR "moved to heap: NAME-z" +func foo78a(z int) *int { // ERROR "moved to heap: z" y := &z // ERROR "&z escapes to heap" x := &y // ERROR "&y does not escape" return *x // really return y @@ -606,19 +606,19 @@ type LimitedFooer struct { N int64 } -func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: NAME-r" - return &LimitedFooer{r, n} // ERROR "&struct literal escapes to heap" +func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r" + return &LimitedFooer{r, n} // ERROR "&LimitedFooer literal escapes to heap" } -func foo90(x *int) map[*int]*int { // ERROR "leaking param: NAME-x" - return map[*int]*int{nil: x} // ERROR "map literal escapes to heap" +func foo90(x *int) map[*int]*int { // ERROR "leaking param: x" + return map[*int]*int{nil: x} // ERROR "map\[\*int\] \*int literal escapes to heap" } -func foo91(x *int) map[*int]*int { // ERROR "leaking param: NAME-x" - return map[*int]*int{x: nil} // ERROR "map literal escapes to heap" +func foo91(x *int) map[*int]*int { // ERROR "leaking param: x" + return map[*int]*int{x: nil} // ERROR "map\[\*int\] \*int literal escapes to heap" } -func foo92(x *int) [2]*int { // ERROR "leaking param: NAME-x" +func foo92(x *int) [2]*int { // ERROR "leaking param: x" return [2]*int{x, nil} } @@ -642,7 +642,7 @@ func foo94(m map[*int]*int, b bool) *int { // ERROR "m does not escape" } // does leak x -func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape" "leaking param: NAME-x" +func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape" "leaking param: x" m[x] = x } @@ -652,7 +652,7 @@ func foo96(m []*int) *int { // ERROR "m does not escape" } // does leak m -func foo97(m [1]*int) *int { // ERROR "leaking param: NAME-m" +func foo97(m [1]*int) *int { // ERROR "leaking param: m" return m[0] } @@ -662,7 +662,7 @@ func foo98(m map[int]*int) *int { // ERROR "m does not escape" } // does leak m -func foo99(m *[1]*int) []*int { // ERROR "leaking param: NAME-m" +func foo99(m *[1]*int) []*int { // ERROR "leaking param: m" return m[:] } @@ -675,7 +675,7 @@ func foo100(m []*int) *int { // ERROR "m does not escape" } // does leak m -func foo101(m [1]*int) *int { // ERROR "leaking param: NAME-m" +func foo101(m [1]*int) *int { // ERROR "leaking param: m" for _, v := range m { return v } @@ -684,14 +684,14 @@ func foo101(m [1]*int) *int { // ERROR "leaking param: NAME-m" // does not leak m func foo101a(m [1]*int) *int { // ERROR "m does not escape" - for i := range m { // ERROR "moved to heap: NAME-i" + for i := range m { // ERROR "moved to heap: i" return &i // ERROR "&i escapes to heap" } return nil } // does leak x -func foo102(m []*int, x *int) { // ERROR "m does not escape" "leaking param: NAME-x" +func foo102(m []*int, x *int) { // ERROR "m does not escape" "leaking param: x" m[0] = x } @@ -713,79 +713,79 @@ func foo105(x []*int) { // ERROR "x does not escape" } // does leak x -func foo106(x *int) { // ERROR "leaking param: NAME-x" +func foo106(x *int) { // ERROR "leaking param: x" _ = append(y, x) } -func foo107(x *int) map[*int]*int { // ERROR "leaking param: NAME-x" - return map[*int]*int{x: nil} // ERROR "map literal escapes to heap" +func foo107(x *int) map[*int]*int { // ERROR "leaking param: x" + return map[*int]*int{x: nil} // ERROR "map.* literal escapes to heap" } -func foo108(x *int) map[*int]*int { // ERROR "leaking param: NAME-x" - return map[*int]*int{nil: x} // ERROR "map literal escapes to heap" +func foo108(x *int) map[*int]*int { // ERROR "leaking param: x" + return map[*int]*int{nil: x} // ERROR "map.* literal escapes to heap" } -func foo109(x *int) *int { // ERROR "leaking param: NAME-x" - m := map[*int]*int{x: nil} // ERROR "map literal does not escape" +func foo109(x *int) *int { // ERROR "leaking param: x" + m := map[*int]*int{x: nil} // ERROR "map.* literal does not escape" for k, _ := range m { return k } return nil } -func foo110(x *int) *int { // ERROR "leaking param: NAME-x" - m := map[*int]*int{nil: x} // ERROR "map literal does not escape" +func foo110(x *int) *int { // ERROR "leaking param: x" + m := map[*int]*int{nil: x} // ERROR "map.* literal does not escape" return m[nil] } -func foo111(x *int) *int { // ERROR "leaking param: NAME-x" - m := []*int{x} // ERROR "slice literal does not escape" +func foo111(x *int) *int { // ERROR "leaking param: x" + m := []*int{x} // ERROR "\[\]\*int literal does not escape" return m[0] } -func foo112(x *int) *int { // ERROR "leaking param: NAME-x" +func foo112(x *int) *int { // ERROR "leaking param: x" m := [1]*int{x} return m[0] } -func foo113(x *int) *int { // ERROR "leaking param: NAME-x" +func foo113(x *int) *int { // ERROR "leaking param: x" m := Bar{ii: x} return m.ii } -func foo114(x *int) *int { // ERROR "leaking param: NAME-x" - m := &Bar{ii: x} // ERROR "&struct literal does not escape" +func foo114(x *int) *int { // ERROR "leaking param: x" + m := &Bar{ii: x} // ERROR "&Bar literal does not escape" return m.ii } -func foo115(x *int) *int { // ERROR "leaking param: NAME-x" +func foo115(x *int) *int { // ERROR "leaking param: x" return (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + 1)) } func foo116(b bool) *int { if b { - x := 1 // ERROR "moved to heap: NAME-x" + x := 1 // ERROR "moved to heap: x" return &x // ERROR "&x escapes to heap" } else { - y := 1 // ERROR "moved to heap: NAME-y" + y := 1 // ERROR "moved to heap: y" return &y // ERROR "&y escapes to heap" } return nil } func foo117(unknown func(interface{})) { // ERROR "unknown does not escape" - x := 1 // ERROR "moved to heap: NAME-x" + x := 1 // ERROR "moved to heap: x" unknown(&x) // ERROR "&x escapes to heap" } func foo118(unknown func(*int)) { // ERROR "unknown does not escape" - x := 1 // ERROR "moved to heap: NAME-x" + x := 1 // ERROR "moved to heap: x" unknown(&x) // ERROR "&x escapes to heap" } func external(*int) -func foo119(x *int) { // ERROR "leaking param: NAME-x" +func foo119(x *int) { // ERROR "leaking param: x" external(x) }