Type*
tointerface(NodeList *l)
{
- Type *t, *f, **tp, *t1;
+ Type *t, *f, **tp, **otp, *t1;
t = typ(TINTER);
+ t->orig = typ(TINTER);
- for(tp = &t->type; l; l=l->next) {
+ tp = &t->type;
+ otp = &t->orig->type;
+
+ for(; l; l=l->next) {
f = interfacefield(l->n);
+ *otp = typ(TFIELD);
+ **otp = *f;
+ otp = &(*otp)->down;
+
if (l->n->left == N && f->type->etype == TINTER) {
// embedded interface, inline methods
for(t1=f->type->type; t1; t1=t1->down) {
f->type = t1->type;
f->broke = t1->broke;
f->sym = t1->sym;
+ f->embedded = 1;
if(f->sym)
f->nname = newname(f->sym);
*tp = f;
if(t->sym != S && t->etype != TFIELD)
dumppkg(t->sym->pkg);
+ // fmt will print the ->orig of an interface, which has the original embedded interfaces.
+ // be sure to dump them here
+ if(t->etype == TINTER)
+ for(f=t->orig->type; f; f=f->down)
+ if(f->sym == S)
+ dumpexporttype(f->type);
+
dumpexporttype(t->type);
dumpexporttype(t->down);
pt->sym->lastlineno = parserline();
declare(n, PEXTERN);
checkwidth(pt);
- } else if(!eqtype(pt->orig, t))
- yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt->orig, t);
+ } else if(!eqtype(pt->orig, t->orig))
+ yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt, t);
if(debug['E'])
print("import type %T %lT\n", pt, t);
[OCONTINUE] = "continue",
[OCOPY] = "copy",
[ODEC] = "--",
+ [ODELETE] = "delete",
[ODEFER] = "defer",
[ODIV] = "/",
[OEQ] = "==",
return fmtprint(fp, "map[%T]%T", t->down, t->type);
case TINTER:
+ t = t->orig;
fmtstrcpy(fp, "interface {");
for(t1=t->type; t1!=T; t1=t1->down)
- if(exportname(t1->sym->name)) {
+ if(!t1->sym) {
+ if(t1->down)
+ fmtprint(fp, " %T;", t1->type);
+ else
+ fmtprint(fp, " %T ", t1->type);
+ } else if(exportname(t1->sym->name)) {
if(t1->down)
fmtprint(fp, " %hS%hT;", t1->sym, t1->type);
else
[OCONVNOP] = 8,
[OCONV] = 8,
[OCOPY] = 8,
+ [ODELETE] = 8,
[OLEN] = 8,
[OLITERAL] = 8,
[OMAKESLICE] = 8,
[OGT] = 4,
[ONE] = 4,
[OCMPSTR] = 4,
+ [OCMPIFACE] = 4,
[OSEND] = 3,
[OANDAND] = 2,
case OAPPEND:
case OCAP:
case OCLOSE:
+ case ODELETE:
case OLEN:
case OMAKE:
case ONEW:
return 0;
case OCMPSTR:
+ case OCMPIFACE:
exprfmt(f, n->left, nprec);
fmtprint(f, " %#O ", n->etype);
exprfmt(f, n->right, nprec+1);
Type *t;
t = n->type;
- if(n->orig == N)
+ if(n->orig == N) {
+ n->orig = n;
fatal("node with no orig %N", n);
+ }
// we almost always want the original, except in export mode for literals
// this saves the importer some work, and avoids us having to redo some
indent(fp);
}
}
+ fmtprint(fp, "[%p]", n);
switch(n->op) {
default:
$$->list = $2;
if($$->list == nil && curfn != N) {
NodeList *l;
-
+
for(l=curfn->dcl; l; l=l->next) {
if(l->n->class == PPARAM)
continue;
{
$$ = nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
}
+| hidden_type
+ {
+ $$ = nod(ODCLFIELD, N, typenod($1));
+ }
ohidden_funres:
{
return &Func{Params: params, Results: results, IsVariadic: isVariadic}
}
-// MethodSpec = ( identifier | ExportedName ) Signature .
+// MethodOrEmbedSpec = Name [ Signature ] .
//
-func (p *gcParser) parseMethodSpec() *ast.Object {
- if p.tok == scanner.Ident {
- p.expect(scanner.Ident)
- } else {
- p.parseExportedName()
+func (p *gcParser) parseMethodOrEmbedSpec() *ast.Object {
+ p.parseName()
+ if p.tok == '(' {
+ p.parseSignature()
+ // TODO(gri) compute method object
+ return ast.NewObj(ast.Fun, "_")
}
- p.parseSignature()
-
- // TODO(gri) compute method object
- return ast.NewObj(ast.Fun, "_")
+ // TODO lookup name and return that type
+ return ast.NewObj(ast.Typ, "_")
}
-// InterfaceType = "interface" "{" [ MethodList ] "}" .
-// MethodList = MethodSpec { ";" MethodSpec } .
+// InterfaceType = "interface" "{" [ MethodOrEmbedList ] "}" .
+// MethodOrEmbedList = MethodOrEmbedSpec { ";" MethodOrEmbedSpec } .
//
func (p *gcParser) parseInterfaceType() Type {
var methods ObjList
parseMethod := func() {
- meth := p.parseMethodSpec()
- methods = append(methods, meth)
+ switch m := p.parseMethodOrEmbedSpec(); m.Kind {
+ case ast.Typ:
+ // TODO expand embedded methods
+ case ast.Fun:
+ methods = append(methods, m)
+ }
}
p.expectKeyword("interface")
--- /dev/null
+// $G $D/$F.go || echo "Bug395"
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 1909
+// Would OOM due to exponential recursion on Foo's expanded methodset in nodefmt
+package test
+
+type Foo interface {
+ Bar() interface{Foo}
+ Baz() interface{Foo}
+ Bug() interface{Foo}
+}