1
0
mirror of https://github.com/golang/go synced 2024-11-21 21:24:45 -07:00

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
This commit is contained in:
Luuk van Dijk 2011-10-08 19:37:06 +02:00
parent bffadd6bd7
commit b536adbfba
14 changed files with 563 additions and 455 deletions

View File

@ -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";

View File

@ -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;

View File

@ -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*);

View File

@ -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;
}

View File

@ -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*

View File

@ -78,8 +78,6 @@ static void fixlbrace(int);
%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
@ -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
{

View File

@ -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

View File

@ -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)

View File

@ -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, "<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*
@ -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, "<T>");
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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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" .

View File

@ -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

View File

@ -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)
}