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:
parent
bffadd6bd7
commit
b536adbfba
@ -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";
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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*);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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*
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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" .
|
||||
|
@ -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
|
||||
|
204
test/escape2.go
204
test/escape2.go
@ -10,21 +10,21 @@ import "unsafe"
|
||||
|
||||
var gxx *int
|
||||
|
||||
func foo1(x int) { // ERROR "moved to heap: NAME-x"
|
||||
func foo1(x int) { // ERROR "moved to heap: x"
|
||||
gxx = &x // ERROR "&x escapes to heap"
|
||||
}
|
||||
|
||||
func foo2(yy *int) { // ERROR "leaking param: NAME-yy"
|
||||
func foo2(yy *int) { // ERROR "leaking param: yy"
|
||||
gxx = yy
|
||||
}
|
||||
|
||||
func foo3(x int) *int { // ERROR "moved to heap: NAME-x"
|
||||
func foo3(x int) *int { // ERROR "moved to heap: x"
|
||||
return &x // ERROR "&x escapes to heap"
|
||||
}
|
||||
|
||||
type T *T
|
||||
|
||||
func foo3b(t T) { // ERROR "leaking param: NAME-t"
|
||||
func foo3b(t T) { // ERROR "leaking param: t"
|
||||
*t = t
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ func foo5(xx **int, yy *int) { // ERROR "xx does not escape" "yy does not escape
|
||||
xx = &yy // ERROR "&yy does not escape"
|
||||
}
|
||||
|
||||
func foo6(xx **int, yy *int) { // ERROR "xx does not escape" "leaking param: NAME-yy"
|
||||
func foo6(xx **int, yy *int) { // ERROR "xx does not escape" "leaking param: yy"
|
||||
*xx = yy
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ func foo8(xx, yy *int) int { // ERROR "xx does not escape" "yy does not escape"
|
||||
return *xx
|
||||
}
|
||||
|
||||
func foo9(xx, yy *int) *int { // ERROR "leaking param: NAME-xx" "leaking param: NAME-yy"
|
||||
func foo9(xx, yy *int) *int { // ERROR "leaking param: xx" "leaking param: yy"
|
||||
xx = yy
|
||||
return xx
|
||||
}
|
||||
@ -70,7 +70,7 @@ func foo11() int {
|
||||
|
||||
var xxx **int
|
||||
|
||||
func foo12(yyy **int) { // ERROR "leaking param: NAME-yyy"
|
||||
func foo12(yyy **int) { // ERROR "leaking param: yyy"
|
||||
xxx = yyy
|
||||
}
|
||||
|
||||
@ -82,11 +82,11 @@ func foo14(yyy **int) { // ERROR "yyy does not escape"
|
||||
**xxx = **yyy
|
||||
}
|
||||
|
||||
func foo15(yy *int) { // ERROR "moved to heap: NAME-yy"
|
||||
func foo15(yy *int) { // ERROR "moved to heap: yy"
|
||||
xxx = &yy // ERROR "&yy escapes to heap"
|
||||
}
|
||||
|
||||
func foo16(yy *int) { // ERROR "leaking param: NAME-yy"
|
||||
func foo16(yy *int) { // ERROR "leaking param: yy"
|
||||
*xxx = yy
|
||||
}
|
||||
|
||||
@ -94,7 +94,7 @@ func foo17(yy *int) { // ERROR "yy does not escape"
|
||||
**xxx = *yy
|
||||
}
|
||||
|
||||
func foo18(y int) { // ERROR "moved to heap: "NAME-y"
|
||||
func foo18(y int) { // ERROR "moved to heap: "y"
|
||||
*xxx = &y // ERROR "&y escapes to heap"
|
||||
}
|
||||
|
||||
@ -108,15 +108,15 @@ type Bar struct {
|
||||
}
|
||||
|
||||
func NewBar() *Bar {
|
||||
return &Bar{42, nil} // ERROR "&struct literal escapes to heap"
|
||||
return &Bar{42, nil} // ERROR "&Bar literal escapes to heap"
|
||||
}
|
||||
|
||||
func NewBarp(x *int) *Bar { // ERROR "leaking param: NAME-x"
|
||||
return &Bar{42, x} // ERROR "&struct literal escapes to heap"
|
||||
func NewBarp(x *int) *Bar { // ERROR "leaking param: x"
|
||||
return &Bar{42, x} // ERROR "&Bar literal escapes to heap"
|
||||
}
|
||||
|
||||
func NewBarp2(x *int) *Bar { // ERROR "x does not escape"
|
||||
return &Bar{*x, nil} // ERROR "&struct literal escapes to heap"
|
||||
return &Bar{*x, nil} // ERROR "&Bar literal escapes to heap"
|
||||
}
|
||||
|
||||
func (b *Bar) NoLeak() int { // ERROR "b does not escape"
|
||||
@ -127,7 +127,7 @@ func (b *Bar) AlsoNoLeak() *int { // ERROR "b does not escape"
|
||||
return b.ii
|
||||
}
|
||||
|
||||
func goLeak(b *Bar) { // ERROR "leaking param: NAME-b"
|
||||
func goLeak(b *Bar) { // ERROR "leaking param: b"
|
||||
go b.NoLeak()
|
||||
}
|
||||
|
||||
@ -137,14 +137,14 @@ type Bar2 struct {
|
||||
}
|
||||
|
||||
func NewBar2() *Bar2 {
|
||||
return &Bar2{[12]int{42}, nil} // ERROR "&struct literal escapes to heap"
|
||||
return &Bar2{[12]int{42}, nil} // ERROR "&Bar2 literal escapes to heap"
|
||||
}
|
||||
|
||||
func (b *Bar2) NoLeak() int { // ERROR "b does not escape"
|
||||
return b.i[0]
|
||||
}
|
||||
|
||||
func (b *Bar2) Leak() []int { // ERROR "leaking param: NAME-b"
|
||||
func (b *Bar2) Leak() []int { // ERROR "leaking param: b"
|
||||
return b.i[:] // ERROR "&b.i escapes to heap"
|
||||
}
|
||||
|
||||
@ -152,18 +152,18 @@ func (b *Bar2) AlsoNoLeak() []int { // ERROR "b does not escape"
|
||||
return b.ii[0:1]
|
||||
}
|
||||
|
||||
func (b *Bar2) LeakSelf() { // ERROR "leaking param: NAME-b"
|
||||
func (b *Bar2) LeakSelf() { // ERROR "leaking param: b"
|
||||
b.ii = b.i[0:4] // ERROR "&b.i escapes to heap"
|
||||
}
|
||||
|
||||
func (b *Bar2) LeakSelf2() { // ERROR "leaking param: NAME-b"
|
||||
func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b"
|
||||
var buf []int
|
||||
buf = b.i[0:] // ERROR "&b.i escapes to heap"
|
||||
b.ii = buf
|
||||
}
|
||||
|
||||
func foo21() func() int {
|
||||
x := 42 // ERROR "moved to heap: NAME-x"
|
||||
x := 42 // ERROR "moved to heap: x"
|
||||
return func() int { // ERROR "func literal escapes to heap"
|
||||
return x // ERROR "&x escapes to heap"
|
||||
}
|
||||
@ -176,21 +176,21 @@ func foo22() int {
|
||||
}()
|
||||
}
|
||||
|
||||
func foo23(x int) func() int { // ERROR "moved to heap: NAME-x"
|
||||
func foo23(x int) func() int { // ERROR "moved to heap: x"
|
||||
return func() int { // ERROR "func literal escapes to heap"
|
||||
return x // ERROR "&x escapes to heap"
|
||||
}
|
||||
}
|
||||
|
||||
func foo23a(x int) func() int { // ERROR "moved to heap: NAME-x"
|
||||
func foo23a(x int) func() int { // ERROR "moved to heap: x"
|
||||
f := func() int { // ERROR "func literal escapes to heap"
|
||||
return x // ERROR "&x escapes to heap"
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func foo23b(x int) *(func() int) { // ERROR "moved to heap: NAME-x"
|
||||
f := func() int { return x } // ERROR "moved to heap: NAME-f" "func literal escapes to heap" "&x escapes to heap"
|
||||
func foo23b(x int) *(func() int) { // ERROR "moved to heap: x"
|
||||
f := func() int { return x } // ERROR "moved to heap: f" "func literal escapes to heap" "&x escapes to heap"
|
||||
return &f // ERROR "&f escapes to heap"
|
||||
}
|
||||
|
||||
@ -202,7 +202,7 @@ func foo24(x int) int {
|
||||
|
||||
var x *int
|
||||
|
||||
func fooleak(xx *int) int { // ERROR "leaking param: NAME-xx"
|
||||
func fooleak(xx *int) int { // ERROR "leaking param: xx"
|
||||
x = xx
|
||||
return *x
|
||||
}
|
||||
@ -211,7 +211,7 @@ func foonoleak(xx *int) int { // ERROR "xx does not escape"
|
||||
return *x + *xx
|
||||
}
|
||||
|
||||
func foo31(x int) int { // ERROR "moved to heap: NAME-x"
|
||||
func foo31(x int) int { // ERROR "moved to heap: x"
|
||||
return fooleak(&x) // ERROR "&x escapes to heap"
|
||||
}
|
||||
|
||||
@ -227,7 +227,7 @@ type Foo struct {
|
||||
var F Foo
|
||||
var pf *Foo
|
||||
|
||||
func (f *Foo) fooleak() { // ERROR "leaking param: NAME-f"
|
||||
func (f *Foo) fooleak() { // ERROR "leaking param: f"
|
||||
pf = f
|
||||
}
|
||||
|
||||
@ -235,7 +235,7 @@ func (f *Foo) foonoleak() { // ERROR "f does not escape"
|
||||
F.x = f.x
|
||||
}
|
||||
|
||||
func (f *Foo) Leak() { // ERROR "leaking param: NAME-f"
|
||||
func (f *Foo) Leak() { // ERROR "leaking param: f"
|
||||
f.fooleak()
|
||||
}
|
||||
|
||||
@ -243,19 +243,19 @@ func (f *Foo) NoLeak() { // ERROR "f does not escape"
|
||||
f.foonoleak()
|
||||
}
|
||||
|
||||
func foo41(x int) { // ERROR "moved to heap: NAME-x"
|
||||
func foo41(x int) { // ERROR "moved to heap: x"
|
||||
F.xx = &x // ERROR "&x escapes to heap"
|
||||
}
|
||||
|
||||
func (f *Foo) foo42(x int) { // ERROR "f does not escape" "moved to heap: NAME-x"
|
||||
func (f *Foo) foo42(x int) { // ERROR "f does not escape" "moved to heap: x"
|
||||
f.xx = &x // ERROR "&x escapes to heap"
|
||||
}
|
||||
|
||||
func foo43(f *Foo, x int) { // ERROR "f does not escape" "moved to heap: NAME-x"
|
||||
func foo43(f *Foo, x int) { // ERROR "f does not escape" "moved to heap: x"
|
||||
f.xx = &x // ERROR "&x escapes to heap"
|
||||
}
|
||||
|
||||
func foo44(yy *int) { // ERROR "leaking param: NAME-yy"
|
||||
func foo44(yy *int) { // ERROR "leaking param: yy"
|
||||
F.xx = yy
|
||||
}
|
||||
|
||||
@ -267,31 +267,31 @@ func (f *Foo) foo46() { // ERROR "f does not escape"
|
||||
F.xx = f.xx
|
||||
}
|
||||
|
||||
func (f *Foo) foo47() { // ERROR "leaking param: NAME-f"
|
||||
func (f *Foo) foo47() { // ERROR "leaking param: f"
|
||||
f.xx = &f.x // ERROR "&f.x escapes to heap"
|
||||
}
|
||||
|
||||
var ptrSlice []*int
|
||||
|
||||
func foo50(i *int) { // ERROR "leaking param: NAME-i"
|
||||
func foo50(i *int) { // ERROR "leaking param: i"
|
||||
ptrSlice[0] = i
|
||||
}
|
||||
|
||||
var ptrMap map[*int]*int
|
||||
|
||||
func foo51(i *int) { // ERROR "leaking param: NAME-i"
|
||||
func foo51(i *int) { // ERROR "leaking param: i"
|
||||
ptrMap[i] = i
|
||||
}
|
||||
|
||||
func indaddr1(x int) *int { // ERROR "moved to heap: NAME-x"
|
||||
func indaddr1(x int) *int { // ERROR "moved to heap: x"
|
||||
return &x // ERROR "&x escapes to heap"
|
||||
}
|
||||
|
||||
func indaddr2(x *int) *int { // ERROR "leaking param: NAME-x"
|
||||
func indaddr2(x *int) *int { // ERROR "leaking param: x"
|
||||
return *&x // ERROR "&x does not escape"
|
||||
}
|
||||
|
||||
func indaddr3(x *int32) *int { // ERROR "leaking param: NAME-x"
|
||||
func indaddr3(x *int32) *int { // ERROR "leaking param: x"
|
||||
return *(**int)(unsafe.Pointer(&x)) // ERROR "&x does not escape"
|
||||
}
|
||||
|
||||
@ -314,26 +314,26 @@ func Float64frombits(b uint64) float64 {
|
||||
}
|
||||
|
||||
// contrast with
|
||||
func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: NAME-f"
|
||||
func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f"
|
||||
return (*uint64)(unsafe.Pointer(&f)) // ERROR "&f escapes to heap"
|
||||
}
|
||||
|
||||
func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: NAME-f"
|
||||
func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f"
|
||||
return (*uint64)(unsafe.Pointer(f))
|
||||
}
|
||||
|
||||
func typesw(i interface{}) *int { // ERROR "leaking param: NAME-i"
|
||||
func typesw(i interface{}) *int { // ERROR "leaking param: i"
|
||||
switch val := i.(type) {
|
||||
case *int:
|
||||
return val
|
||||
case *int8:
|
||||
v := int(*val) // ERROR "moved to heap: NAME-v"
|
||||
v := int(*val) // ERROR "moved to heap: v"
|
||||
return &v // ERROR "&v escapes to heap"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func exprsw(i *int) *int { // ERROR "leaking param: NAME-i"
|
||||
func exprsw(i *int) *int { // ERROR "leaking param: i"
|
||||
switch j := i; *j + 110 {
|
||||
case 12:
|
||||
return j
|
||||
@ -345,7 +345,7 @@ func exprsw(i *int) *int { // ERROR "leaking param: NAME-i"
|
||||
}
|
||||
|
||||
// assigning to an array element is like assigning to the array
|
||||
func foo60(i *int) *int { // ERROR "leaking param: NAME-i"
|
||||
func foo60(i *int) *int { // ERROR "leaking param: i"
|
||||
var a [12]*int
|
||||
a[0] = i
|
||||
return a[1]
|
||||
@ -358,7 +358,7 @@ func foo60a(i *int) *int { // ERROR "i does not escape"
|
||||
}
|
||||
|
||||
// assigning to a struct field is like assigning to the struct
|
||||
func foo61(i *int) *int { // ERROR "leaking param: NAME-i"
|
||||
func foo61(i *int) *int { // ERROR "leaking param: i"
|
||||
type S struct {
|
||||
a, b *int
|
||||
}
|
||||
@ -379,7 +379,7 @@ func foo61a(i *int) *int { // ERROR "i does not escape"
|
||||
// assigning to a struct field is like assigning to the struct but
|
||||
// here this subtlety is lost, since s.a counts as an assignment to a
|
||||
// track-losing dereference.
|
||||
func foo62(i *int) *int { // ERROR "leaking param: NAME-i"
|
||||
func foo62(i *int) *int { // ERROR "leaking param: i"
|
||||
type S struct {
|
||||
a, b *int
|
||||
}
|
||||
@ -395,11 +395,11 @@ type M interface {
|
||||
func foo63(m M) { // ERROR "m does not escape"
|
||||
}
|
||||
|
||||
func foo64(m M) { // ERROR "leaking param: NAME-m"
|
||||
func foo64(m M) { // ERROR "leaking param: m"
|
||||
m.M()
|
||||
}
|
||||
|
||||
func foo64b(m M) { // ERROR "leaking param: NAME-m"
|
||||
func foo64b(m M) { // ERROR "leaking param: m"
|
||||
defer m.M()
|
||||
}
|
||||
|
||||
@ -413,7 +413,7 @@ func foo65() {
|
||||
}
|
||||
|
||||
func foo66() {
|
||||
var mv MV // ERROR "moved to heap: NAME-mv"
|
||||
var mv MV // ERROR "moved to heap: mv"
|
||||
foo64(&mv) // ERROR "&mv escapes to heap"
|
||||
}
|
||||
|
||||
@ -427,22 +427,22 @@ func foo68() {
|
||||
foo64(mv) // escapes but it's an int so irrelevant
|
||||
}
|
||||
|
||||
func foo69(m M) { // ERROR "leaking param: NAME-m"
|
||||
func foo69(m M) { // ERROR "leaking param: m"
|
||||
foo64(m)
|
||||
}
|
||||
|
||||
func foo70(mv1 *MV, m M) { // ERROR "leaking param: NAME-mv1" "leaking param: NAME-m"
|
||||
func foo70(mv1 *MV, m M) { // ERROR "leaking param: mv1" "leaking param: m"
|
||||
m = mv1
|
||||
foo64(m)
|
||||
}
|
||||
|
||||
func foo71(x *int) []*int { // ERROR "leaking param: NAME-x"
|
||||
func foo71(x *int) []*int { // ERROR "leaking param: x"
|
||||
var y []*int
|
||||
y = append(y, x)
|
||||
return y
|
||||
}
|
||||
|
||||
func foo71a(x int) []*int { // ERROR "moved to heap: NAME-x"
|
||||
func foo71a(x int) []*int { // ERROR "moved to heap: x"
|
||||
var y []*int
|
||||
y = append(y, &x) // ERROR "&x escapes to heap"
|
||||
return y
|
||||
@ -455,7 +455,7 @@ func foo72() {
|
||||
}
|
||||
|
||||
func foo72aa() [10]*int {
|
||||
var x int // ERROR "moved to heap: NAME-x"
|
||||
var x int // ERROR "moved to heap: x"
|
||||
var y [10]*int
|
||||
y[0] = &x // ERROR "&x escapes to heap"
|
||||
return y
|
||||
@ -465,7 +465,7 @@ func foo72a() {
|
||||
var y [10]*int
|
||||
for i := 0; i < 10; i++ {
|
||||
// escapes its scope
|
||||
x := i // ERROR "moved to heap: NAME-x"
|
||||
x := i // ERROR "moved to heap: x"
|
||||
y[i] = &x // ERROR "&x escapes to heap"
|
||||
}
|
||||
return
|
||||
@ -474,7 +474,7 @@ func foo72a() {
|
||||
func foo72b() [10]*int {
|
||||
var y [10]*int
|
||||
for i := 0; i < 10; i++ {
|
||||
x := i // ERROR "moved to heap: NAME-x"
|
||||
x := i // ERROR "moved to heap: x"
|
||||
y[i] = &x // ERROR "&x escapes to heap"
|
||||
}
|
||||
return y
|
||||
@ -482,9 +482,9 @@ func foo72b() [10]*int {
|
||||
|
||||
// issue 2145
|
||||
func foo73() {
|
||||
s := []int{3, 2, 1} // ERROR "slice literal does not escape"
|
||||
s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
|
||||
for _, v := range s {
|
||||
vv := v // ERROR "moved to heap: NAME-vv"
|
||||
vv := v // ERROR "moved to heap: vv"
|
||||
// actually just escapes its scope
|
||||
defer func() { // ERROR "func literal escapes to heap"
|
||||
println(vv) // ERROR "&vv escapes to heap"
|
||||
@ -493,9 +493,9 @@ func foo73() {
|
||||
}
|
||||
|
||||
func foo74() {
|
||||
s := []int{3, 2, 1} // ERROR "slice literal does not escape"
|
||||
s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
|
||||
for _, v := range s {
|
||||
vv := v // ERROR "moved to heap: NAME-vv"
|
||||
vv := v // ERROR "moved to heap: vv"
|
||||
// actually just escapes its scope
|
||||
fn := func() { // ERROR "func literal escapes to heap"
|
||||
println(vv) // ERROR "&vv escapes to heap"
|
||||
@ -504,15 +504,15 @@ func foo74() {
|
||||
}
|
||||
}
|
||||
|
||||
func myprint(y *int, x ...interface{}) *int { // ERROR "x does not escape" "leaking param: NAME-y"
|
||||
func myprint(y *int, x ...interface{}) *int { // ERROR "x does not escape" "leaking param: y"
|
||||
return y
|
||||
}
|
||||
|
||||
func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "y does not escape" "leaking param: NAME-x"
|
||||
func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "y does not escape" "leaking param: x"
|
||||
return &x[0] // ERROR "&x.0. escapes to heap"
|
||||
}
|
||||
|
||||
func foo75(z *int) { // ERROR "leaking param: NAME-z"
|
||||
func foo75(z *int) { // ERROR "leaking param: z"
|
||||
myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
|
||||
}
|
||||
|
||||
@ -520,11 +520,11 @@ func foo75a(z *int) { // ERROR "z does not escape"
|
||||
myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
|
||||
}
|
||||
|
||||
func foo76(z *int) { // ERROR "leaking param: NAME-z"
|
||||
func foo76(z *int) { // ERROR "leaking param: z"
|
||||
myprint(nil, z) // ERROR "[.][.][.] argument does not escape"
|
||||
}
|
||||
|
||||
func foo76a(z *int) { // ERROR "leaking param: NAME-z"
|
||||
func foo76a(z *int) { // ERROR "leaking param: z"
|
||||
myprint1(nil, z) // ERROR "[.][.][.] argument escapes to heap"
|
||||
}
|
||||
|
||||
@ -561,15 +561,15 @@ func foo77(z []interface{}) { // ERROR "z does not escape"
|
||||
myprint(nil, z...) // z does not escape
|
||||
}
|
||||
|
||||
func foo77a(z []interface{}) { // ERROR "leaking param: NAME-z"
|
||||
func foo77a(z []interface{}) { // ERROR "leaking param: z"
|
||||
myprint1(nil, z...)
|
||||
}
|
||||
|
||||
func foo78(z int) *int { // ERROR "moved to heap: NAME-z"
|
||||
func foo78(z int) *int { // ERROR "moved to heap: z"
|
||||
return &z // ERROR "&z escapes to heap"
|
||||
}
|
||||
|
||||
func foo78a(z int) *int { // ERROR "moved to heap: NAME-z"
|
||||
func foo78a(z int) *int { // ERROR "moved to heap: z"
|
||||
y := &z // ERROR "&z escapes to heap"
|
||||
x := &y // ERROR "&y does not escape"
|
||||
return *x // really return y
|
||||
@ -606,19 +606,19 @@ type LimitedFooer struct {
|
||||
N int64
|
||||
}
|
||||
|
||||
func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: NAME-r"
|
||||
return &LimitedFooer{r, n} // ERROR "&struct literal escapes to heap"
|
||||
func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r"
|
||||
return &LimitedFooer{r, n} // ERROR "&LimitedFooer literal escapes to heap"
|
||||
}
|
||||
|
||||
func foo90(x *int) map[*int]*int { // ERROR "leaking param: NAME-x"
|
||||
return map[*int]*int{nil: x} // ERROR "map literal escapes to heap"
|
||||
func foo90(x *int) map[*int]*int { // ERROR "leaking param: x"
|
||||
return map[*int]*int{nil: x} // ERROR "map\[\*int\] \*int literal escapes to heap"
|
||||
}
|
||||
|
||||
func foo91(x *int) map[*int]*int { // ERROR "leaking param: NAME-x"
|
||||
return map[*int]*int{x: nil} // ERROR "map literal escapes to heap"
|
||||
func foo91(x *int) map[*int]*int { // ERROR "leaking param: x"
|
||||
return map[*int]*int{x: nil} // ERROR "map\[\*int\] \*int literal escapes to heap"
|
||||
}
|
||||
|
||||
func foo92(x *int) [2]*int { // ERROR "leaking param: NAME-x"
|
||||
func foo92(x *int) [2]*int { // ERROR "leaking param: x"
|
||||
return [2]*int{x, nil}
|
||||
}
|
||||
|
||||
@ -642,7 +642,7 @@ func foo94(m map[*int]*int, b bool) *int { // ERROR "m does not escape"
|
||||
}
|
||||
|
||||
// does leak x
|
||||
func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape" "leaking param: NAME-x"
|
||||
func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape" "leaking param: x"
|
||||
m[x] = x
|
||||
}
|
||||
|
||||
@ -652,7 +652,7 @@ func foo96(m []*int) *int { // ERROR "m does not escape"
|
||||
}
|
||||
|
||||
// does leak m
|
||||
func foo97(m [1]*int) *int { // ERROR "leaking param: NAME-m"
|
||||
func foo97(m [1]*int) *int { // ERROR "leaking param: m"
|
||||
return m[0]
|
||||
}
|
||||
|
||||
@ -662,7 +662,7 @@ func foo98(m map[int]*int) *int { // ERROR "m does not escape"
|
||||
}
|
||||
|
||||
// does leak m
|
||||
func foo99(m *[1]*int) []*int { // ERROR "leaking param: NAME-m"
|
||||
func foo99(m *[1]*int) []*int { // ERROR "leaking param: m"
|
||||
return m[:]
|
||||
}
|
||||
|
||||
@ -675,7 +675,7 @@ func foo100(m []*int) *int { // ERROR "m does not escape"
|
||||
}
|
||||
|
||||
// does leak m
|
||||
func foo101(m [1]*int) *int { // ERROR "leaking param: NAME-m"
|
||||
func foo101(m [1]*int) *int { // ERROR "leaking param: m"
|
||||
for _, v := range m {
|
||||
return v
|
||||
}
|
||||
@ -684,14 +684,14 @@ func foo101(m [1]*int) *int { // ERROR "leaking param: NAME-m"
|
||||
|
||||
// does not leak m
|
||||
func foo101a(m [1]*int) *int { // ERROR "m does not escape"
|
||||
for i := range m { // ERROR "moved to heap: NAME-i"
|
||||
for i := range m { // ERROR "moved to heap: i"
|
||||
return &i // ERROR "&i escapes to heap"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// does leak x
|
||||
func foo102(m []*int, x *int) { // ERROR "m does not escape" "leaking param: NAME-x"
|
||||
func foo102(m []*int, x *int) { // ERROR "m does not escape" "leaking param: x"
|
||||
m[0] = x
|
||||
}
|
||||
|
||||
@ -713,79 +713,79 @@ func foo105(x []*int) { // ERROR "x does not escape"
|
||||
}
|
||||
|
||||
// does leak x
|
||||
func foo106(x *int) { // ERROR "leaking param: NAME-x"
|
||||
func foo106(x *int) { // ERROR "leaking param: x"
|
||||
_ = append(y, x)
|
||||
}
|
||||
|
||||
func foo107(x *int) map[*int]*int { // ERROR "leaking param: NAME-x"
|
||||
return map[*int]*int{x: nil} // ERROR "map literal escapes to heap"
|
||||
func foo107(x *int) map[*int]*int { // ERROR "leaking param: x"
|
||||
return map[*int]*int{x: nil} // ERROR "map.* literal escapes to heap"
|
||||
}
|
||||
|
||||
func foo108(x *int) map[*int]*int { // ERROR "leaking param: NAME-x"
|
||||
return map[*int]*int{nil: x} // ERROR "map literal escapes to heap"
|
||||
func foo108(x *int) map[*int]*int { // ERROR "leaking param: x"
|
||||
return map[*int]*int{nil: x} // ERROR "map.* literal escapes to heap"
|
||||
}
|
||||
|
||||
func foo109(x *int) *int { // ERROR "leaking param: NAME-x"
|
||||
m := map[*int]*int{x: nil} // ERROR "map literal does not escape"
|
||||
func foo109(x *int) *int { // ERROR "leaking param: x"
|
||||
m := map[*int]*int{x: nil} // ERROR "map.* literal does not escape"
|
||||
for k, _ := range m {
|
||||
return k
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func foo110(x *int) *int { // ERROR "leaking param: NAME-x"
|
||||
m := map[*int]*int{nil: x} // ERROR "map literal does not escape"
|
||||
func foo110(x *int) *int { // ERROR "leaking param: x"
|
||||
m := map[*int]*int{nil: x} // ERROR "map.* literal does not escape"
|
||||
return m[nil]
|
||||
}
|
||||
|
||||
func foo111(x *int) *int { // ERROR "leaking param: NAME-x"
|
||||
m := []*int{x} // ERROR "slice literal does not escape"
|
||||
func foo111(x *int) *int { // ERROR "leaking param: x"
|
||||
m := []*int{x} // ERROR "\[\]\*int literal does not escape"
|
||||
return m[0]
|
||||
}
|
||||
|
||||
func foo112(x *int) *int { // ERROR "leaking param: NAME-x"
|
||||
func foo112(x *int) *int { // ERROR "leaking param: x"
|
||||
m := [1]*int{x}
|
||||
return m[0]
|
||||
}
|
||||
|
||||
func foo113(x *int) *int { // ERROR "leaking param: NAME-x"
|
||||
func foo113(x *int) *int { // ERROR "leaking param: x"
|
||||
m := Bar{ii: x}
|
||||
return m.ii
|
||||
}
|
||||
|
||||
func foo114(x *int) *int { // ERROR "leaking param: NAME-x"
|
||||
m := &Bar{ii: x} // ERROR "&struct literal does not escape"
|
||||
func foo114(x *int) *int { // ERROR "leaking param: x"
|
||||
m := &Bar{ii: x} // ERROR "&Bar literal does not escape"
|
||||
return m.ii
|
||||
}
|
||||
|
||||
func foo115(x *int) *int { // ERROR "leaking param: NAME-x"
|
||||
func foo115(x *int) *int { // ERROR "leaking param: x"
|
||||
return (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + 1))
|
||||
}
|
||||
|
||||
func foo116(b bool) *int {
|
||||
if b {
|
||||
x := 1 // ERROR "moved to heap: NAME-x"
|
||||
x := 1 // ERROR "moved to heap: x"
|
||||
return &x // ERROR "&x escapes to heap"
|
||||
} else {
|
||||
y := 1 // ERROR "moved to heap: NAME-y"
|
||||
y := 1 // ERROR "moved to heap: y"
|
||||
return &y // ERROR "&y escapes to heap"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func foo117(unknown func(interface{})) { // ERROR "unknown does not escape"
|
||||
x := 1 // ERROR "moved to heap: NAME-x"
|
||||
x := 1 // ERROR "moved to heap: x"
|
||||
unknown(&x) // ERROR "&x escapes to heap"
|
||||
}
|
||||
|
||||
func foo118(unknown func(*int)) { // ERROR "unknown does not escape"
|
||||
x := 1 // ERROR "moved to heap: NAME-x"
|
||||
x := 1 // ERROR "moved to heap: x"
|
||||
unknown(&x) // ERROR "&x escapes to heap"
|
||||
}
|
||||
|
||||
func external(*int)
|
||||
|
||||
func foo119(x *int) { // ERROR "leaking param: NAME-x"
|
||||
func foo119(x *int) { // ERROR "leaking param: x"
|
||||
external(x)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user