ok:
n = pt->nod;
- *pt = *t;
- pt->method = nil;
+ copytype(pt->nod, t);
+ // unzero nod
pt->nod = n;
- pt->sym = n->sym;
+
pt->sym->lastlineno = parserline();
- pt->siggen = 0;
- pt->printed = 0;
- pt->deferwidth = 0;
- pt->local = 0;
declare(n, PEXTERN);
checkwidth(pt);
*/
Node* callnew(Type *t);
Node* chanfn(char *name, int n, Type *t);
+void copytype(Node *n, Type *t);
+void defertypecopy(Node *n, Type *t);
Node* mkcall(char *name, Type *t, NodeList **init, ...);
Node* mkcall1(Node *fn, Type *t, NodeList **init, ...);
void queuemethod(Node *n);
+void resumetypecopy(void);
int vmatch1(Node *l, Node *r);
void walk(Node *fn);
Node* walkdef(Node *n);
for(l=xtop; l; l=l->next)
if(l->n->op == ODCL || l->n->op == OAS)
typecheck(&l->n, Etop);
+ resumetypecopy();
resumecheckwidth();
for(l=xtop; l; l=l->next)
if(l->n->op == ODCLFUNC)
static void checkassignlist(NodeList*);
static void stringtoarraylit(Node**);
static Node* resolve(Node*);
+static Type* getforwtype(Node*);
/*
* resolve ONONAME to definition, if any.
Node *n, *l, *r;
NodeList *args;
int lno, ok, ntop;
- Type *t, *tp, *missing, *have;
+ Type *t, *tp, *ft, *missing, *have;
Sym *sym;
Val v;
char *why;
yyerror("use of builtin %S not in function call", n->sym);
goto error;
}
+
+ // a dance to handle forward-declared recursive pointer types.
+ if(n->op == OTYPE && (ft = getforwtype(n->ntype)) != T)
+ defertypecopy(n, ft);
+
walkdef(n);
n->realtype = n->type;
if(n->op == ONONAME)
typecheck(&nn, Erv);
*np = nn;
}
+
+static Type*
+getforwtype(Node *n)
+{
+ Node *f1, *f2;
+
+ for(f1=f2=n; ; n=n->ntype) {
+ if((n = resolve(n)) == N || n->op != OTYPE)
+ return T;
+
+ if(n->type != T && n->type->etype == TFORW)
+ return n->type;
+
+ // Check for ntype cycle.
+ if((f2 = resolve(f2)) != N && (f1 = resolve(f2->ntype)) != N) {
+ f2 = resolve(f1->ntype);
+ if(f1 == n || f2 == n)
+ return T;
+ }
+ }
+}
checkwidth(n->type);
}
+typedef struct NodeTypeList NodeTypeList;
+struct NodeTypeList {
+ Node *n;
+ Type *t;
+ NodeTypeList *next;
+};
+
+static NodeTypeList *dntq;
+static NodeTypeList *dntend;
+
+void
+defertypecopy(Node *n, Type *t)
+{
+ NodeTypeList *ntl;
+
+ if(n == N || t == T)
+ return;
+
+ ntl = mal(sizeof *ntl);
+ ntl->n = n;
+ ntl->t = t;
+ ntl->next = nil;
+
+ if(dntq == nil)
+ dntq = ntl;
+ else
+ dntend->next = ntl;
+
+ dntend = ntl;
+}
+
+void
+resumetypecopy(void)
+{
+ NodeTypeList *l;
+
+ for(l=dntq; l; l=l->next)
+ copytype(l->n, l->t);
+}
+
+void
+copytype(Node *n, Type *t)
+{
+ *n->type = *t;
+
+ t = n->type;
+ t->sym = n->sym;
+ t->local = n->local;
+ t->vargen = n->vargen;
+ t->siggen = 0;
+ t->method = nil;
+ t->nod = N;
+ t->printed = 0;
+ t->deferwidth = 0;
+}
+
static void
walkdeftype(Node *n)
{
goto ret;
}
+ maplineno = n->type->maplineno;
+ embedlineno = n->type->embedlineno;
+
// copy new type and clear fields
// that don't come along.
// anything zeroed here must be zeroed in
// typedcl2 too.
- maplineno = n->type->maplineno;
- embedlineno = n->type->embedlineno;
- *n->type = *t;
- t = n->type;
- t->sym = n->sym;
- t->local = n->local;
- t->vargen = n->vargen;
- t->siggen = 0;
- t->method = nil;
- t->nod = N;
- t->printed = 0;
- t->deferwidth = 0;
+ copytype(n, t);
// double-check use of type as map key.
if(maplineno) {
--- /dev/null
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// 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.
+
+package main
+
+type T1 struct {
+ Next *T2
+}
+
+type T2 T1
+
+type T3 struct {
+ Next *T4
+}
+
+type T4 T5
+type T5 T6
+type T6 T7
+type T7 T8
+type T8 T9
+type T9 T3
+
+type T10 struct {
+ x struct {
+ y ***struct {
+ z *struct {
+ Next *T11
+ }
+ }
+ }
+}
+
+type T11 T10
+
+type T12 struct {
+ F1 *T15
+ F2 *T13
+ F3 *T16
+}
+
+type T13 T14
+type T14 T15
+type T15 T16
+type T16 T17
+type T17 T12
+
+// issue 1672
+type T18 *[10]T19
+type T19 T18
+
+func main() {
+ _ = &T1{&T2{}}
+ _ = &T2{&T2{}}
+ _ = &T3{&T4{}}
+ _ = &T4{&T4{}}
+ _ = &T5{&T4{}}
+ _ = &T6{&T4{}}
+ _ = &T7{&T4{}}
+ _ = &T8{&T4{}}
+ _ = &T9{&T4{}}
+ _ = &T12{&T15{}, &T13{}, &T16{}}
+
+ var (
+ tn struct{ Next *T11 }
+ tz struct{ z *struct{ Next *T11 } }
+ tpz *struct{ z *struct{ Next *T11 } }
+ tppz **struct{ z *struct{ Next *T11 } }
+ tpppz ***struct{ z *struct{ Next *T11 } }
+ ty struct {
+ y ***struct{ z *struct{ Next *T11 } }
+ }
+ )
+ tn.Next = &T11{}
+ tz.z = &tn
+ tpz = &tz
+ tppz = &tpz
+ tpppz = &tppz
+ ty.y = tpppz
+ _ = &T10{ty}
+
+ t19s := &[10]T19{}
+ _ = T18(t19s)
+}