Skip to content

Commit 565b5dc

Browse files
committed
gc: new typechecking rules
* Code for assignment, conversions now mirrors spec. * Changed some snprint -> smprint. * Renamed runtime functions to separate interface conversions from type assertions: convT2I, assertI2T, etc. * Correct checking of \U sequences. Fixes #840. Fixes #830. Fixes #778. R=ken2 CC=golang-dev https://golang.org/cl/1303042
1 parent 6aaef04 commit 565b5dc

29 files changed

+1469
-1330
lines changed

src/cmd/6g/cgen.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ agen(Node *n, Node *res)
431431
if(n == N || n->type == T)
432432
return;
433433

434-
if(!isptr[res->type->etype])
434+
if(!isptr[res->type->etype] && res->type->etype != TUINTPTR)
435435
fatal("agen: not tptr: %T", res->type);
436436

437437
while(n->op == OCONVNOP)

src/cmd/gc/bits.c

+11-14
Original file line numberDiff line numberDiff line change
@@ -133,25 +133,22 @@ bitno(int32 b)
133133
int
134134
Qconv(Fmt *fp)
135135
{
136-
char str[STRINGSZ], ss[STRINGSZ], *s;
137136
Bits bits;
138-
int i;
137+
int i, first;
139138

140-
str[0] = 0;
139+
first = 1;
141140
bits = va_arg(fp->args, Bits);
142141
while(bany(&bits)) {
143142
i = bnum(bits);
144-
if(str[0])
145-
strcat(str, " ");
146-
if(var[i].sym == S) {
147-
sprint(ss, "$%lld", var[i].offset);
148-
s = ss;
149-
} else
150-
s = var[i].sym->name;
151-
if(strlen(str) + strlen(s) + 1 >= STRINGSZ)
152-
break;
153-
strcat(str, s);
143+
if(first)
144+
first = 0;
145+
else
146+
fmtprint(fp, " ");
147+
if(var[i].sym == S)
148+
fmtprint(fp, "$%lld", var[i].offset);
149+
else
150+
fmtprint(fp, var[i].sym->name);
154151
bits.b[i/32] &= ~(1L << (i%32));
155152
}
156-
return fmtstrcpy(fp, str);
153+
return 0;
157154
}

src/cmd/gc/builtin.c.boot

+16-12
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,22 @@ char *runtimeimport =
3333
"func \"\".stringiter (? string, ? int) int\n"
3434
"func \"\".stringiter2 (? string, ? int) (retk int, retv int)\n"
3535
"func \"\".slicecopy (to any, fr any, wid uint32) int\n"
36-
"func \"\".ifaceI2E (iface any) any\n"
37-
"func \"\".ifaceE2I (typ *uint8, iface any) any\n"
38-
"func \"\".ifaceT2E (typ *uint8, elem any) any\n"
39-
"func \"\".ifaceE2T (typ *uint8, elem any) any\n"
40-
"func \"\".ifaceE2I2 (typ *uint8, iface any) (ret any, ok bool)\n"
41-
"func \"\".ifaceE2T2 (typ *uint8, elem any) (ret any, ok bool)\n"
42-
"func \"\".ifaceT2I (typ1 *uint8, typ2 *uint8, elem any) any\n"
43-
"func \"\".ifaceI2T (typ *uint8, iface any) any\n"
44-
"func \"\".ifaceI2T2 (typ *uint8, iface any) (ret any, ok bool)\n"
45-
"func \"\".ifaceI2I (typ *uint8, iface any) any\n"
46-
"func \"\".ifaceI2Ix (typ *uint8, iface any) any\n"
47-
"func \"\".ifaceI2I2 (typ *uint8, iface any) (ret any, ok bool)\n"
36+
"func \"\".convI2E (elem any) any\n"
37+
"func \"\".convI2I (typ *uint8, elem any) any\n"
38+
"func \"\".convT2E (typ *uint8, elem any) any\n"
39+
"func \"\".convT2I (typ *uint8, typ2 *uint8, elem any) any\n"
40+
"func \"\".assertE2E (typ *uint8, iface any) any\n"
41+
"func \"\".assertE2E2 (typ *uint8, iface any) (ret any, ok bool)\n"
42+
"func \"\".assertE2I (typ *uint8, iface any) any\n"
43+
"func \"\".assertE2I2 (typ *uint8, iface any) (ret any, ok bool)\n"
44+
"func \"\".assertE2T (typ *uint8, iface any) any\n"
45+
"func \"\".assertE2T2 (typ *uint8, iface any) (ret any, ok bool)\n"
46+
"func \"\".assertI2E (typ *uint8, iface any) any\n"
47+
"func \"\".assertI2E2 (typ *uint8, iface any) (ret any, ok bool)\n"
48+
"func \"\".assertI2I (typ *uint8, iface any) any\n"
49+
"func \"\".assertI2I2 (typ *uint8, iface any) (ret any, ok bool)\n"
50+
"func \"\".assertI2T (typ *uint8, iface any) any\n"
51+
"func \"\".assertI2T2 (typ *uint8, iface any) (ret any, ok bool)\n"
4852
"func \"\".ifaceeq (i1 any, i2 any) bool\n"
4953
"func \"\".efaceeq (i1 any, i2 any) bool\n"
5054
"func \"\".ifacethash (i1 any) uint32\n"

src/cmd/gc/closure.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ walkclosure(Node *func, NodeList **init)
119119
Node *xtype, *v, *addr, *xfunc, *call, *clos;
120120
NodeList *l, *in;
121121
static int closgen;
122+
char *p;
122123

123124
/*
124125
* wrap body in external function
@@ -134,8 +135,9 @@ walkclosure(Node *func, NodeList **init)
134135
if(v->op == 0)
135136
continue;
136137
addr = nod(ONAME, N, N);
137-
snprint(namebuf, sizeof namebuf, "&%s", v->sym->name);
138-
addr->sym = lookup(namebuf);
138+
p = smprint("&%s", v->sym->name);
139+
addr->sym = lookup(p);
140+
free(p);
139141
addr->ntype = nod(OIND, typenod(v->type), N);
140142
addr->class = PPARAM;
141143
addr->addable = 1;

src/cmd/gc/const.c

+7-4
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,11 @@ convlit1(Node **np, Type *t, int explicit)
9393
return;
9494
case OLITERAL:
9595
// target is invalid type for a constant? leave alone.
96-
if(!okforconst[t->etype] && n->type->etype != TNIL)
96+
if(!okforconst[t->etype] && n->type->etype != TNIL) {
97+
defaultlit(&n, T);
98+
*np = n;
9799
return;
100+
}
98101
break;
99102
case OLSH:
100103
case ORSH:
@@ -109,10 +112,8 @@ convlit1(Node **np, Type *t, int explicit)
109112
}
110113

111114
// avoided repeated calculations, errors
112-
if(cvttype(n->type, t) == 1) {
113-
n->type = t;
115+
if(eqtype(n->type, t))
114116
return;
115-
}
116117

117118
ct = consttype(n);
118119
if(ct < 0)
@@ -968,6 +969,8 @@ defaultlit(Node **np, Type *t)
968969
break;
969970
case CTBOOL:
970971
n->type = types[TBOOL];
972+
if(t != T && t->etype == TBOOL)
973+
n->type = t;
971974
break;
972975
case CTINT:
973976
n->type = types[TINT];

src/cmd/gc/dcl.c

+12-7
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ updatetype(Type *n, Type *t)
281281
local = n->local;
282282
vargen = n->vargen;
283283
*n = *t;
284+
n->orig = t->orig;
284285
n->sym = s;
285286
n->local = local;
286287
n->siggen = 0;
@@ -759,7 +760,7 @@ typedcl2(Type *pt, Type *t)
759760

760761
if(pt->etype == TFORW)
761762
goto ok;
762-
if(!cvttype(pt, t))
763+
if(!eqtype(pt->orig, t))
763764
yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt, t);
764765
return;
765766

@@ -1154,7 +1155,7 @@ Sym*
11541155
methodsym(Sym *nsym, Type *t0)
11551156
{
11561157
Sym *s;
1157-
char buf[NSYMB];
1158+
char *p;
11581159
Type *t;
11591160

11601161
t = t0;
@@ -1177,8 +1178,10 @@ methodsym(Sym *nsym, Type *t0)
11771178
if(t != t0 && t0->sym)
11781179
t0 = ptrto(t);
11791180

1180-
snprint(buf, sizeof(buf), "%#hT·%s", t0, nsym->name);
1181-
return pkglookup(buf, s->pkg);
1181+
p = smprint("%#hT·%s", t0, nsym->name);
1182+
s = pkglookup(p, s->pkg);
1183+
free(p);
1184+
return s;
11821185

11831186
bad:
11841187
yyerror("illegal receiver type: %T", t0);
@@ -1200,7 +1203,7 @@ Node*
12001203
methodname1(Node *n, Node *t)
12011204
{
12021205
char *star;
1203-
char buf[NSYMB];
1206+
char *p;
12041207

12051208
star = "";
12061209
if(t->op == OIND) {
@@ -1209,8 +1212,10 @@ methodname1(Node *n, Node *t)
12091212
}
12101213
if(t->sym == S || isblank(n))
12111214
return newname(n->sym);
1212-
snprint(buf, sizeof(buf), "%s%S·%S", star, t->sym, n->sym);
1213-
return newname(pkglookup(buf, t->sym->pkg));
1215+
p = smprint("%s%S·%S", star, t->sym, n->sym);
1216+
n = newname(pkglookup(p, t->sym->pkg));
1217+
free(p);
1218+
return n;
12141219
}
12151220

12161221
/*

src/cmd/gc/export.c

+25-4
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,22 @@ dumpexporttype(Sym *s)
182182
Bprint(bout, "type %#T %l#T\n", t, t);
183183
}
184184

185+
static int
186+
methcmp(const void *va, const void *vb)
187+
{
188+
Type *a, *b;
189+
190+
a = *(Type**)va;
191+
b = *(Type**)vb;
192+
return strcmp(a->sym->name, b->sym->name);
193+
}
194+
185195
void
186196
dumpsym(Sym *s)
187197
{
188198
Type *f, *t;
199+
Type **m;
200+
int i, n;
189201

190202
if(s->flags & SymExported)
191203
return;
@@ -207,14 +219,23 @@ dumpsym(Sym *s)
207219
break;
208220
case OTYPE:
209221
t = s->def->type;
210-
// TODO(rsc): sort methods by name
211-
for(f=t->method; f!=T; f=f->down)
222+
n = 0;
223+
for(f=t->method; f!=T; f=f->down) {
212224
dumpprereq(f);
225+
n++;
226+
}
227+
m = mal(n*sizeof m[0]);
228+
i = 0;
229+
for(f=t->method; f!=T; f=f->down)
230+
m[i++] = f;
231+
qsort(m, n, sizeof m[0], methcmp);
213232

214233
dumpexporttype(s);
215-
for(f=t->method; f!=T; f=f->down)
234+
for(i=0; i<n; i++) {
235+
f = m[i];
216236
Bprint(bout, "\tfunc (%#T) %hS %#hhT\n",
217237
f->type->type->type, f->sym, f->type);
238+
}
218239
break;
219240
case ONAME:
220241
dumpexportvar(s);
@@ -357,7 +378,7 @@ importvar(Sym *s, Type *t, int ctxt)
357378

358379
importsym(s, ONAME);
359380
if(s->def != N && s->def->op == ONAME) {
360-
if(cvttype(t, s->def->type))
381+
if(eqtype(t, s->def->type))
361382
return;
362383
yyerror("inconsistent definition for var %S during import\n\t%T\n\t%T",
363384
s, s->def->type, t);

src/cmd/gc/go.h

+9-16
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ struct Type
158158
uchar isddd; // TFIELD is ... argument
159159

160160
Node* nod; // canonical OTYPE node
161+
Type* orig; // original type (type literal or predefined type)
161162
int lineno;
162163

163164
// TFUNCT
@@ -361,11 +362,12 @@ enum
361362
OCLOSURE,
362363
OCMPIFACE, OCMPSTR,
363364
OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT,
364-
OCONV, OCONVNOP, OCONVIFACE, OCONVSLICE,
365+
OCONV, OCONVIFACE, OCONVNOP, OCONVSLICE,
365366
OCOPY,
366367
ODCL, ODCLFUNC, ODCLFIELD, ODCLCONST, ODCLTYPE,
367368
ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT,
368369
ODOTTYPE,
370+
ODOTTYPE2,
369371
OEQ, ONE, OLT, OLE, OGE, OGT,
370372
OIND,
371373
OINDEX, OINDEXSTR, OINDEXMAP,
@@ -904,26 +906,21 @@ NodeList* list(NodeList*, Node*);
904906
NodeList* concat(NodeList*, NodeList*);
905907
int count(NodeList*);
906908
Node* liststmt(NodeList*);
907-
908909
Type** getthis(Type*);
909910
Type** getoutarg(Type*);
910911
Type** getinarg(Type*);
911-
912912
Type* getthisx(Type*);
913913
Type* getoutargx(Type*);
914914
Type* getinargx(Type*);
915-
916915
Type* structfirst(Iter*, Type**);
917916
Type* structnext(Iter*);
918917
Type* funcfirst(Iter*, Type*);
919918
Type* funcnext(Iter*);
920-
921919
int brcom(int);
922920
int brrev(int);
923921
void setmaxarg(Type*);
924922
int dotoffset(Node*, int*, Node**);
925923
void tempname(Node*, Type*);
926-
927924
int Econv(Fmt*);
928925
int Jconv(Fmt*);
929926
int Lconv(Fmt*);
@@ -934,23 +931,22 @@ int Nconv(Fmt*);
934931
void exprfmt(Fmt*, Node*, int);
935932
int Wconv(Fmt*);
936933
int Zconv(Fmt*);
937-
938934
int lookdot0(Sym*, Type*, Type**);
939935
int adddot1(Sym*, Type*, int, Type**);
940936
Node* adddot(Node*);
941937
void expandmeth(Sym*, Type*);
942938
void genwrapper(Type*, Type*, Sym*);
943-
944939
int simsimtype(Type*);
945-
946940
int powtwo(Node*);
947941
Type* tounsigned(Type*);
948942
void smagic(Magic*);
949943
void umagic(Magic*);
950-
951944
void redeclare(Sym*, char*);
952945
Sym* ngotype(Node*);
953-
946+
int convertop(Type*, Type*, char**);
947+
int assignop(Type*, Type*, char**);
948+
Node* assignconv(Node*, Type*, char*);
949+
int implements(Type*, Type*, Type**, Type**);
954950

955951
/*
956952
* dcl.c
@@ -1053,7 +1049,6 @@ void walkstmt(Node**);
10531049
void walkstmtlist(NodeList*);
10541050
void walkexprlist(NodeList*, NodeList**);
10551051
void walkconv(Node**, NodeList**);
1056-
void walkdottype(Node*, NodeList**);
10571052
void walkas(Node*);
10581053
void walkswitch(Node*);
10591054
void walkrange(Node*);
@@ -1071,8 +1066,6 @@ Type* fixchan(Type*);
10711066
Node* ifacecvt(Type*, Node*, int, NodeList**);
10721067
int ifaceas(Type*, Type*, int);
10731068
int ifaceas1(Type*, Type*, int);
1074-
void ifacecheck(Type*, Type*, int, int);
1075-
void runifacechecks(void);
10761069
Node* convas(Node*, NodeList**);
10771070
Node* colas(NodeList*, NodeList*);
10781071
void colasdefn(NodeList*, Node*);
@@ -1090,10 +1083,10 @@ void typecheckswitch(Node*);
10901083
void typecheckselect(Node*);
10911084
void typecheckrange(Node*);
10921085
Node* typecheckconv(Node*, Node*, Type*, int, char*);
1093-
int checkconv(Type*, Type*, int, int*, int*, char*);
10941086
Node* typecheck(Node**, int);
10951087
int islvalue(Node*);
10961088
void queuemethod(Node*);
1089+
int exportassignok(Type*, char*);
10971090

10981091
/*
10991092
* const.c
@@ -1242,4 +1235,4 @@ int duintptr(Sym *s, int off, uint64 v);
12421235
int duintxx(Sym *s, int off, uint64 v, int wid);
12431236
void genembedtramp(Type*, Type*, Sym*);
12441237
int gen_as_init(Node*);
1245-
int anyregalloc();
1238+
int anyregalloc(void);

0 commit comments

Comments
 (0)