From 9c5669bd0b7f65903776dcc0a6bd10578c6e42e2 Mon Sep 17 00:00:00 2001 From: Ken Thompson Date: Tue, 2 Sep 2008 16:21:30 -0700 Subject: [PATCH] bug in conv(string, bytearray) R=r OCL=14732 CL=14732 --- src/cmd/gc/go.h | 3 +- src/cmd/gc/subr.c | 12 +++-- src/cmd/gc/walk.c | 133 +++++++++++++++++++++++++++++----------------- 3 files changed, 93 insertions(+), 55 deletions(-) diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index c2d46e23f5d..121a019e57d 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -559,7 +559,7 @@ int isptrto(Type*, int); int isptrarray(Type*); int isptrdarray(Type*); int isinter(Type*); -int isbytearray(Type*); +int bytearraysz(Type*); int eqtype(Type*, Type*, int); void argtype(Node*, Type*); int eqargs(Type*, Type*); @@ -689,6 +689,7 @@ Node* reorder1(Node*); Node* reorder2(Node*); Node* reorder3(Node*); Node* reorder4(Node*); +Node* structlit(Node*); /* * const.c diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index b925e5061e1..56958caff9b 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -1229,18 +1229,20 @@ isinter(Type *t) } int -isbytearray(Type *t) +bytearraysz(Type *t) { if(t == T) - return 0; + return -2; if(isptr[t->etype]) { t = t->type; if(t == T) - return 0; + return -2; } if(t->etype != TARRAY) - return 0; - return t->bound+1; + return -2; + if(!eqtype(t->type, types[TUINT8], 0)) + return -2; + return t->bound; // -1 is dyn, >=0 is fixed } int diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index b9ec0c1e108..f44106695c1 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -8,6 +8,7 @@ static Type* sw1(Node*, Type*); static Type* sw2(Node*, Type*); static Type* sw3(Node*, Type*); static Node* curfn; +static Node* addtop; void walk(Node *fn) @@ -38,7 +39,7 @@ isselect(Node *n) } void -walktype(Node *n, int top) +walktype1(Node *n, int top) { Node *r, *l; Type *t; @@ -54,11 +55,6 @@ walktype(Node *n, int top) * compile-time constants are evaluated. */ - if(top == Exxx || top == Eyyy) { - dump("", n); - fatal("walktype: bad top=%d", top); - } - loop: if(n == N) goto ret; @@ -76,6 +72,11 @@ loop: fatal("walktype: switch 1 unknown op %N", n); goto ret; + case OLIST: + walktype(n->left, top); + n = n->right; + goto loop; + case OPRINT: if(top != Etop) goto nottop; @@ -120,11 +121,6 @@ loop: } goto ret; - case OLIST: - walktype(n->left, top); - n = n->right; - goto loop; - case OFOR: if(top != Etop) goto nottop; @@ -400,6 +396,8 @@ loop: goto ret; convlit(l, t); + if(l->type == T) + goto ret; // nil conversion if(eqtype(t, l->type, 0)) { @@ -422,7 +420,7 @@ loop: *n = *stringop(n, top); goto ret; } - if(isbytearray(l->type) != 0) { + if(bytearraysz(l->type) != -2) { n->op = OARRAY; *n = *stringop(n, top); goto ret; @@ -433,16 +431,20 @@ loop: if(isptrarray(t) && isptrdarray(l->type)) goto ret; -// if(t->etype == TARRAY) { -// arrayconv(t, l); -// goto ret; -// } - + // interface and structure r = isandss(n->type, l); if(r != N) { *n = *r; goto ret; } + + // structure literal + if(t->etype == TSTRUCT) { + r = structlit(n); + *n = *r; + goto ret; + } + badtype(n->op, l->type, t); goto ret; @@ -1591,6 +1593,7 @@ Node* stringop(Node *n, int top) { Node *r, *c, *on; + Type *t; int32 l; switch(n->op) { @@ -1674,15 +1677,24 @@ stringop(Node *n, int top) break; case OARRAY: - // byteastring(a, l) + // byteastring(*byte, int32) string; + t = n->left->type; + l = bytearraysz(t); + + // &a[0] c = nodintconst(0); r = nod(OINDEX, n->left, c); r = nod(OADDR, r, N); - l = isbytearray(n->left->type); - c = nodintconst(l-1); - + if(l >= 0) { + // static size + c = nodintconst(l); + } else { + // dynamic size + c = nod(OLEN, n->left, N); + } r = list(r, c); + on = syslook("byteastring", 0); r = nod(OCALL, on, r); break; @@ -2309,6 +2321,20 @@ arrayop(Node *n, int top) return r; } +void +walktype(Node *n, int top) +{ + Node *r; + + walktype1(n, top); + while(top == Etop && addtop != N) { + r = addtop; + addtop = N; + walktype1(r, top); + n->ninit = list(r, n->ninit); + } +} + void diagnamed(Type *t) { @@ -2420,34 +2446,6 @@ bad: return n; } -//void -//arrayconv(Type *t, Node *n) -//{ -// int c; -// Iter save; -// Node *l; -// -// l = listfirst(&save, &n); -// c = 0; -// -//loop: -// if(l == N) { -// if(t->bound == 0) -// t->bound = c; -// if(t->bound == 0 || t->bound < c) -// yyerror("error with array convert bounds"); -// return; -// } -// -// c++; -// walktype(l, Erv); -// convlit(l, t->type); -// if(!ascompat(l->type, t->type)) -// badtype(OARRAY, l->type, t->type); -// l = listnext(&save); -// goto loop; -//} - Node* old2new(Node *n, Type *t) { @@ -2818,3 +2816,40 @@ reorder4(Node *n) */ return n; } + +Node* +structlit(Node *n) +{ + Iter savel, saver; + Type *l, *t; + Node *var, *r, *a; + + t = n->type; + if(t->etype != TSTRUCT) + fatal("structlit: not struct"); + +print("\nstruct lit %lT\n", t); + + var = nod(OXXX, N, N); + tempname(var, t); + + l = structfirst(&savel, &n->type); + r = listfirst(&saver, &n->left); + +loop: + if(l == T || r == N) { + if(l != T || r != N) + yyerror("error in shape struct literal"); + return var; + } + + // build list of var.field = expr + + a = nod(ODOT, var, newname(l->sym)); + a = nod(OAS, a, r); + addtop = list(addtop, a); + + l = structnext(&savel); + r = listnext(&saver); + goto loop; +}