OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 /* | 5 /* |
6 * type check the whole tree of an expression. | 6 * type check the whole tree of an expression. |
7 * calculates expression types. | 7 * calculates expression types. |
8 * evaluates compile time constants. | 8 * evaluates compile time constants. |
9 * marks variables that escape the local frame. | 9 * marks variables that escape the local frame. |
10 * rewrites n->op to be more specific in some cases. | 10 * rewrites n->op to be more specific in some cases. |
(...skipping 15 matching lines...) Expand all Loading... |
26 static void typecheckas2(Node*); | 26 static void typecheckas2(Node*); |
27 static void typecheckas(Node*); | 27 static void typecheckas(Node*); |
28 static void typecheckfunc(Node*); | 28 static void typecheckfunc(Node*); |
29 static void checklvalue(Node*, char*); | 29 static void checklvalue(Node*, char*); |
30 static void checkassign(Node*); | 30 static void checkassign(Node*); |
31 static void checkassignlist(NodeList*); | 31 static void checkassignlist(NodeList*); |
32 static void stringtoarraylit(Node**); | 32 static void stringtoarraylit(Node**); |
33 static Node* resolve(Node*); | 33 static Node* resolve(Node*); |
34 static void checkdefergo(Node*); | 34 static void checkdefergo(Node*); |
35 static int checkmake(Type*, char*, Node*); | 35 static int checkmake(Type*, char*, Node*); |
| 36 static int checksliceindex(Node*, Type*); |
| 37 static int checksliceconst(Node*, Node*); |
36 | 38 |
37 static NodeList* typecheckdefstack; | 39 static NodeList* typecheckdefstack; |
38 | 40 |
39 /* | 41 /* |
40 * resolve ONONAME to definition, if any. | 42 * resolve ONONAME to definition, if any. |
41 */ | 43 */ |
42 static Node* | 44 static Node* |
43 resolve(Node *n) | 45 resolve(Node *n) |
44 { | 46 { |
45 Node *r; | 47 Node *r; |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 defaultlit(np, types[TINT]); | 298 defaultlit(np, types[TINT]); |
297 break; | 299 break; |
298 } | 300 } |
299 defaultlit(np, T); | 301 defaultlit(np, T); |
300 } | 302 } |
301 | 303 |
302 static void | 304 static void |
303 typecheck1(Node **np, int top) | 305 typecheck1(Node **np, int top) |
304 { | 306 { |
305 int et, aop, op, ptr; | 307 int et, aop, op, ptr; |
306 » Node *n, *l, *r; | 308 » Node *n, *l, *r, *lo, *mid, *hi; |
307 NodeList *args; | 309 NodeList *args; |
308 int ok, ntop; | 310 int ok, ntop; |
309 Type *t, *tp, *missing, *have, *badtype; | 311 Type *t, *tp, *missing, *have, *badtype; |
310 Val v; | 312 Val v; |
311 char *why; | 313 char *why; |
312 ········ | 314 ········ |
313 n = *np; | 315 n = *np; |
314 | 316 |
315 if(n->sym) { | 317 if(n->sym) { |
316 if(n->op == ONAME && n->etype != 0 && !(top & Ecall)) { | 318 if(n->op == ONAME && n->etype != 0 && !(top & Ecall)) { |
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 n->type->type = tp->type; | 988 n->type->type = tp->type; |
987 n->type->bound = -1; | 989 n->type->bound = -1; |
988 dowidth(n->type); | 990 dowidth(n->type); |
989 n->op = OSLICEARR; | 991 n->op = OSLICEARR; |
990 } else if(isslice(t)) { | 992 } else if(isslice(t)) { |
991 n->type = t; | 993 n->type = t; |
992 } else { | 994 } else { |
993 yyerror("cannot slice %N (type %T)", l, t); | 995 yyerror("cannot slice %N (type %T)", l, t); |
994 goto error; | 996 goto error; |
995 } | 997 } |
996 » » if(n->right->left != N) { | 998 » » if((lo = n->right->left) != N && checksliceindex(lo, tp) < 0) |
997 » » » if((t = n->right->left->type) == T) | 999 » » » goto error; |
998 » » » » goto error; | 1000 » » if((hi = n->right->right) != N && checksliceindex(hi, tp) < 0) |
999 » » » if(!isint[t->etype]) { | 1001 » » » goto error; |
1000 » » » » yyerror("invalid slice index %N (type %T)", n->r
ight->left, t); | 1002 » » if(checksliceconst(lo, hi) < 0) |
| 1003 » » » goto error; |
| 1004 » » goto ret; |
| 1005 |
| 1006 » case OSLICE3: |
| 1007 » » ok |= Erv; |
| 1008 » » typecheck(&n->left, top); |
| 1009 » » typecheck(&n->right->left, Erv); |
| 1010 » » typecheck(&n->right->right->left, Erv); |
| 1011 » » typecheck(&n->right->right->right, Erv); |
| 1012 » » defaultlit(&n->left, T); |
| 1013 » » indexlit(&n->right->left); |
| 1014 » » indexlit(&n->right->right->left); |
| 1015 » » indexlit(&n->right->right->right); |
| 1016 » » l = n->left; |
| 1017 » » if(isfixedarray(l->type)) { |
| 1018 » » » if(!islvalue(n->left)) { |
| 1019 » » » » yyerror("invalid operation %N (slice of unaddres
sable value)", n); |
1001 goto error; | 1020 goto error; |
1002 } | 1021 } |
1003 » » » if(n->right->left->op == OLITERAL) { | 1022 » » » n->left = nod(OADDR, n->left, N); |
1004 » » » » if(mpgetfix(n->right->left->val.u.xval) < 0) { | 1023 » » » n->left->implicit = 1; |
1005 » » » » » yyerror("invalid slice index %N (index m
ust be non-negative)", n->right->left); | 1024 » » » typecheck(&n->left, Erv); |
1006 » » » » » goto error; | 1025 » » » l = n->left; |
1007 » » » » } else if(tp != nil && tp->bound > 0 && mpgetfix
(n->right->left->val.u.xval) > tp->bound) { | |
1008 » » » » » yyerror("invalid slice index %N (out of
bounds for %d-element array)", n->right->left, tp->bound); | |
1009 » » » » » goto error; | |
1010 » » » » } else if(mpcmpfixfix(n->right->left->val.u.xval
, maxintval[TINT]) > 0) { | |
1011 » » » » » yyerror("invalid slice index %N (index t
oo large)", n->right->left); | |
1012 » » » » » goto error; | |
1013 » » » » } | |
1014 » » » } | |
1015 } | 1026 } |
1016 » » if(n->right->right != N) { | 1027 » » if((t = l->type) == T) |
1017 » » » if((t = n->right->right->type) == T) | 1028 » » » goto error; |
1018 » » » » goto error; | 1029 » » tp = nil; |
1019 » » » if(!isint[t->etype]) { | 1030 » » if(istype(t, TSTRING)) { |
1020 » » » » yyerror("invalid slice index %N (type %T)", n->r
ight->right, t); | 1031 » » » yyerror("invalid operation %N (3-index slice of string)"
, n); |
1021 » » » » goto error; | |
1022 » » » } | |
1023 » » » if(n->right->right->op == OLITERAL) { | |
1024 » » » » if(mpgetfix(n->right->right->val.u.xval) < 0) { | |
1025 » » » » » yyerror("invalid slice index %N (index m
ust be non-negative)", n->right->right); | |
1026 » » » » » goto error; | |
1027 » » » » } else if(tp != nil && tp->bound > 0 && mpgetfix
(n->right->right->val.u.xval) > tp->bound) { | |
1028 » » » » » yyerror("invalid slice index %N (out of
bounds for %d-element array)", n->right->right, tp->bound); | |
1029 » » » » » goto error; | |
1030 » » » » } else if(mpcmpfixfix(n->right->right->val.u.xva
l, maxintval[TINT]) > 0) { | |
1031 » » » » » yyerror("invalid slice index %N (index t
oo large)", n->right->right); | |
1032 » » » » » goto error; | |
1033 » » » » } | |
1034 » » » } | |
1035 » » } | |
1036 » » if(n->right->left != N | |
1037 » » && n->right->right != N | |
1038 » » && n->right->left->op == OLITERAL | |
1039 » » && n->right->right->op == OLITERAL | |
1040 » » && mpcmpfixfix(n->right->left->val.u.xval, n->right->right->v
al.u.xval) > 0) { | |
1041 » » » yyerror("inverted slice index %N > %N", n->right->left,
n->right->right); | |
1042 goto error; | 1032 goto error; |
1043 } | 1033 } |
| 1034 if(isptr[t->etype] && isfixedarray(t->type)) { |
| 1035 tp = t->type; |
| 1036 n->type = typ(TARRAY); |
| 1037 n->type->type = tp->type; |
| 1038 n->type->bound = -1; |
| 1039 dowidth(n->type); |
| 1040 n->op = OSLICE3ARR; |
| 1041 } else if(isslice(t)) { |
| 1042 n->type = t; |
| 1043 } else { |
| 1044 yyerror("cannot slice %N (type %T)", l, t); |
| 1045 goto error; |
| 1046 } |
| 1047 if((lo = n->right->left) != N && checksliceindex(lo, tp) < 0) |
| 1048 goto error; |
| 1049 if((mid = n->right->right->left) != N && checksliceindex(mid, tp
) < 0) |
| 1050 goto error; |
| 1051 if((hi = n->right->right->right) != N && checksliceindex(hi, tp)
< 0) |
| 1052 goto error; |
| 1053 if(checksliceconst(lo, hi) < 0 || checksliceconst(lo, mid) < 0 |
| checksliceconst(mid, hi) < 0) |
| 1054 goto error; |
1044 goto ret; | 1055 goto ret; |
1045 | 1056 |
1046 /* | 1057 /* |
1047 * call and call like | 1058 * call and call like |
1048 */ | 1059 */ |
1049 case OCALL: | 1060 case OCALL: |
1050 l = n->left; | 1061 l = n->left; |
1051 if(l->op == ONAME && (r = unsafenmagic(n)) != N) { | 1062 if(l->op == ONAME && (r = unsafenmagic(n)) != N) { |
1052 if(n->isddd) | 1063 if(n->isddd) |
1053 yyerror("invalid use of ... with builtin %N", l)
; | 1064 yyerror("invalid use of ... with builtin %N", l)
; |
(...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1750 yyerror("invalid argument %lN for %O", n->left, n->op); | 1761 yyerror("invalid argument %lN for %O", n->left, n->op); |
1751 goto error; | 1762 goto error; |
1752 | 1763 |
1753 error: | 1764 error: |
1754 n->type = T; | 1765 n->type = T; |
1755 | 1766 |
1756 out: | 1767 out: |
1757 *np = n; | 1768 *np = n; |
1758 } | 1769 } |
1759 | 1770 |
| 1771 static int |
| 1772 checksliceindex(Node *r, Type *tp) |
| 1773 { |
| 1774 Type *t; |
| 1775 |
| 1776 if((t = r->type) == T) |
| 1777 return -1; |
| 1778 if(!isint[t->etype]) { |
| 1779 yyerror("invalid slice index %N (type %T)", r, t); |
| 1780 return -1; |
| 1781 } |
| 1782 if(r->op == OLITERAL) { |
| 1783 if(mpgetfix(r->val.u.xval) < 0) { |
| 1784 yyerror("invalid slice index %N (index must be non-negat
ive)", r); |
| 1785 return -1; |
| 1786 } else if(tp != nil && tp->bound > 0 && mpgetfix(r->val.u.xval)
> tp->bound) { |
| 1787 yyerror("invalid slice index %N (out of bounds for %d-el
ement array)", r, tp->bound); |
| 1788 return -1; |
| 1789 } else if(mpcmpfixfix(r->val.u.xval, maxintval[TINT]) > 0) { |
| 1790 yyerror("invalid slice index %N (index too large)", r); |
| 1791 return -1; |
| 1792 } |
| 1793 } |
| 1794 return 0; |
| 1795 } |
| 1796 |
| 1797 static int |
| 1798 checksliceconst(Node *lo, Node *hi) |
| 1799 { |
| 1800 if(lo != N && hi != N && lo->op == OLITERAL && hi->op == OLITERAL |
| 1801 && mpcmpfixfix(lo->val.u.xval, hi->val.u.xval) > 0) { |
| 1802 yyerror("invalid slice index: %N > %N", lo, hi); |
| 1803 return -1; |
| 1804 } |
| 1805 return 0; |
| 1806 } |
| 1807 |
1760 static void | 1808 static void |
1761 checkdefergo(Node *n) | 1809 checkdefergo(Node *n) |
1762 { | 1810 { |
1763 char *what; | 1811 char *what; |
1764 ········ | 1812 ········ |
1765 what = "defer"; | 1813 what = "defer"; |
1766 if(n->op == OPROC) | 1814 if(n->op == OPROC) |
1767 what = "go"; | 1815 what = "go"; |
1768 | 1816 |
1769 switch(n->left->op) { | 1817 switch(n->left->op) { |
(...skipping 1551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3321 return 0; | 3369 return 0; |
3322 } | 3370 } |
3323 | 3371 |
3324 void | 3372 void |
3325 checkreturn(Node *fn) | 3373 checkreturn(Node *fn) |
3326 { | 3374 { |
3327 if(fn->type->outtuple && fn->nbody != nil) | 3375 if(fn->type->outtuple && fn->nbody != nil) |
3328 if(!isterminating(fn->nbody, 1)) | 3376 if(!isterminating(fn->nbody, 1)) |
3329 yyerrorl(fn->endlineno, "missing return at end of functi
on"); | 3377 yyerrorl(fn->endlineno, "missing return at end of functi
on"); |
3330 } | 3378 } |
OLD | NEW |