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";
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);
}
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;
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;
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;
#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*);
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;
}
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
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);
#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*
%type <node> indcl interfacetype structtype ptrtype
%type <node> recvchantype non_recvchantype othertype fnret_type fntype
-%type <val> hidden_tag
-
%type <sym> hidden_importsym hidden_pkg_importsym
%type <node> hidden_constant hidden_literal hidden_dcl
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
}
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;
}
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;
$$->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:
{
$$ = 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
{
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
}
}
+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) {
case OGE:
case OGT:
case ONE:
+ case OCMPSTR:
nprec = 4;
break;
break;
case OADD:
+ case OADDSTR:
+ case OAND:
case OANDAND:
case OANDNOT:
case ODIV:
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:
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:
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:
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)
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) {
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] = "&",
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, "<S>");
- return 0;
- }
+ if(s == S)
+ return fmtstrcpy(fp, "<S>");
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*
[TBLANK] = "blank",
};
-int
+// Global flag exporting
+// Global flag noargnames
+// 'h' FmtShort
+// 'l' FmtLong
+static int
Tpretty(Fmt *fp, Type *t)
{
Type *t1;
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;
}
fmtprint(fp, "%T", t->type);
if(t->note) {
fmtprint(fp, " ");
- if(exporting)
- fmtprint(fp, ":");
fmtprint(fp, "\"%Z\"", t->note);
}
return 0;
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, "<T>");
- t->trecur++;
- if(t->trecur > 5) {
- fmtprint(fp, "...");
- goto out;
+ if(t->trecur > 4) {
+ return fmtstrcpy(fp, "...");
}
- 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;
- }
- }
-
- if(sharp || exporting)
- fatal("missing %E case during export", t->etype);
-
- 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;
+ t->trecur++;
- case TPTR32:
- case TPTR64:
- fmtprint(fp, "%T", t->type);
- break;
- }
+ sharp = (fp->flags & FmtSharp);
+ minus = (fp->flags & FmtLeft);
+ sf = fp->flags;
+ fp->flags &= ~(FmtSharp|FmtLeft);
-out:
+ if(sharp)
+ exporting++;
+ if(minus)
+ noargnames++;
+ r = Tpretty(fp, t);
+ if(sharp)
+ exporting--;
+ if(minus)
+ noargnames--;
+
+ fp->flags = sf;
t->trecur--;
- return 0;
+ return r;
}
int
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;
}
#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;
}
/*
- * 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;
}
-
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
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
}
// ----------------------------------------------------------------------------
return
}
-// Field = Name Type [ ":" string_lit ] .
+// Field = Name Type [ string_lit ] .
//
func (p *gcParser) parseField() (fld *ast.Object, tag string) {
name := p.parseName()
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)
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()
}
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)
// 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()
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()
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 == ']' {
//
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 != '=' {
//
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
//
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
p.expect(')')
p.expect(scanner.Ident)
p.parseSignature()
+ if p.tok == '{' {
+ p.parseFuncBody()
+ }
}
// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
_ = 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
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
}
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
}
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
}
var xxx **int
-func foo12(yyy **int) { // ERROR "leaking param: NAME-yyy"
+func foo12(yyy **int) { // ERROR "leaking param: yyy"
xxx = yyy
}
**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
}
**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"
}
}
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"
return b.ii
}
-func goLeak(b *Bar) { // ERROR "leaking param: NAME-b"
+func goLeak(b *Bar) { // ERROR "leaking param: b"
go b.NoLeak()
}
}
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"
}
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"
}
}()
}
-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"
}
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
}
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"
}
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
}
F.x = f.x
}
-func (f *Foo) Leak() { // ERROR "leaking param: NAME-f"
+func (f *Foo) Leak() { // ERROR "leaking param: f"
f.fooleak()
}
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
}
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"
}
}
// 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
}
// 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]
}
// 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
}
// 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
}
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()
}
}
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"
}
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
}
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
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
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
// 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"
}
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"
}
}
-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"
}
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"
}
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
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}
}
}
// 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
}
}
// 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]
}
}
// 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[:]
}
}
// 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
}
// 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
}
}
// 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)
}