Commit 1163b1db authored by Russ Cox's avatar Russ Cox

diagnose various conversion problems

R=ken
OCL=17320
CL=17320
parent bc641d1e
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
void void
convlit(Node *n, Type *t) convlit(Node *n, Type *t)
{ {
int et; int et, wt;
if(n == N || t == T) if(n == N || t == T)
return; return;
...@@ -25,18 +25,10 @@ convlit(Node *n, Type *t) ...@@ -25,18 +25,10 @@ convlit(Node *n, Type *t)
} }
et = t->etype; et = t->etype;
switch(et) {
case TARRAY:
case TFUNC:
case TCHAN:
case TMAP:
case TSTRUCT:
// case TPTR32:
// case TPTR64:
return;
}
switch(whatis(n)) { wt = whatis(n);
switch(wt) {
default: default:
goto bad1; goto bad1;
...@@ -125,6 +117,8 @@ convlit(Node *n, Type *t) ...@@ -125,6 +117,8 @@ convlit(Node *n, Type *t)
goto bad2; goto bad2;
if(mpcmpfltfix(fv, maxintval[et]) > 0) if(mpcmpfltfix(fv, maxintval[et]) > 0)
goto bad2; goto bad2;
if(floor(mpgetflt(fv)) != mpgetflt(fv))
goto bad3;
n->val.u.xval = mal(sizeof(*n->val.u.xval)); n->val.u.xval = mal(sizeof(*n->val.u.xval));
mpmovefltfix(n->val.u.xval, fv); mpmovefltfix(n->val.u.xval, fv);
n->val.ctype = CTINT; n->val.ctype = CTINT;
...@@ -144,12 +138,16 @@ convlit(Node *n, Type *t) ...@@ -144,12 +138,16 @@ convlit(Node *n, Type *t)
return; return;
bad1: bad1:
yyerror("illegal conversion of constant to %T", t); yyerror("illegal conversion of %W to %T", wt, t);
return; return;
bad2: bad2:
yyerror("overflow converting constant to %T", t); yyerror("overflow converting constant to %T", t);
return; return;
bad3:
yyerror("cannot convert non-integer constant to %T", t);
return;
} }
void void
...@@ -212,7 +210,7 @@ evconst(Node *n) ...@@ -212,7 +210,7 @@ evconst(Node *n)
nl->val.ctype = CTFLT; nl->val.ctype = CTFLT;
wl = whatis(nl); wl = whatis(nl);
} else { } else {
yyerror("illegal combination of literals %E %E", nl->etype, nr->etype); yyerror("illegal combination of literals %O %E, %E", n->op, wl, wr);
return; return;
} }
} }
...@@ -230,7 +228,7 @@ evconst(Node *n) ...@@ -230,7 +228,7 @@ evconst(Node *n)
switch(TUP(n->op, wl)) { switch(TUP(n->op, wl)) {
default: default:
yyerror("illegal combination of literals %O %E", n->op, nl->etype); yyerror("illegal literal %O %E", n->op, wl);
return; return;
case TUP(OADD, Wlitint): case TUP(OADD, Wlitint):
......
...@@ -27,6 +27,13 @@ dodclvar(Node *n, Type *t) ...@@ -27,6 +27,13 @@ dodclvar(Node *n, Type *t)
dodclvar(n->left, t); dodclvar(n->left, t);
dowidth(t); dowidth(t);
// in case of type checking error,
// use "undefined" type for variable type,
// to avoid fatal in addvar.
if(t == T)
t = typ(TFORW);
addvar(n, t, dclcontext); addvar(n, t, dclcontext);
if(exportadj) if(exportadj)
exportsym(n->sym); exportsym(n->sym);
......
...@@ -598,6 +598,7 @@ Node* syslook(char*, int); ...@@ -598,6 +598,7 @@ Node* syslook(char*, int);
Node* treecopy(Node*); Node* treecopy(Node*);
int isselect(Node*); int isselect(Node*);
void tempname(Node*, Type*); void tempname(Node*, Type*);
int iscomposite(Type*);
Type** getthis(Type*); Type** getthis(Type*);
Type** getoutarg(Type*); Type** getoutarg(Type*);
...@@ -621,6 +622,7 @@ int Oconv(Fmt*); ...@@ -621,6 +622,7 @@ int Oconv(Fmt*);
int Sconv(Fmt*); int Sconv(Fmt*);
int Tconv(Fmt*); int Tconv(Fmt*);
int Nconv(Fmt*); int Nconv(Fmt*);
int Wconv(Fmt*);
int Zconv(Fmt*); int Zconv(Fmt*);
/* /*
......
...@@ -872,6 +872,8 @@ pexpr: ...@@ -872,6 +872,8 @@ pexpr:
{ {
$$ = nod(OCONV, $3, N); $$ = nod(OCONV, $3, N);
$$->type = oldtype($1); $$->type = oldtype($1);
if(iscomposite($$->type))
yyerror("illegal conversion type %T", $$->type);
} }
| convtype '{' braced_keyexpr_list '}' | convtype '{' braced_keyexpr_list '}'
{ {
...@@ -879,6 +881,8 @@ pexpr: ...@@ -879,6 +881,8 @@ pexpr:
$$ = rev($3); $$ = rev($3);
if($$ == N) if($$ == N)
$$ = nod(OEMPTY, N, N); $$ = nod(OEMPTY, N, N);
if(!iscomposite($1))
yyerror("illegal composite literal type %T", $1);
$$ = nod(OCONV, $$, N); $$ = nod(OCONV, $$, N);
$$->type = $1; $$->type = $1;
} }
......
...@@ -53,6 +53,7 @@ mainlex(int argc, char *argv[]) ...@@ -53,6 +53,7 @@ mainlex(int argc, char *argv[])
fmtinstall('Z', Zconv); // escaped string fmtinstall('Z', Zconv); // escaped string
fmtinstall('L', Lconv); // line number fmtinstall('L', Lconv); // line number
fmtinstall('B', Bconv); // big numbers fmtinstall('B', Bconv); // big numbers
fmtinstall('W', Wconv); // whatis numbers (Wlitint)
lexinit(); lexinit();
lineno = 1; lineno = 1;
......
...@@ -822,6 +822,8 @@ etnames[] = ...@@ -822,6 +822,8 @@ etnames[] =
[TSTRING] = "STRING", [TSTRING] = "STRING",
[TCHAN] = "CHAN", [TCHAN] = "CHAN",
[TANY] = "ANY", [TANY] = "ANY",
[TFORWINTER] = "FORWINTER",
[TFORWSTRUCT] = "FORWSTRUCT",
}; };
int int
...@@ -1327,6 +1329,36 @@ out: ...@@ -1327,6 +1329,36 @@ out:
return fmtstrcpy(fp, buf); return fmtstrcpy(fp, buf);
} }
static char*
wnames[] =
{
[Wnil] = "Wnil",
[Wtnil] = "Wtnil",
[Wtfloat] = "Wtfloat",
[Wtint] = "Wtint",
[Wtbool] = "Wtbool",
[Wtstr] = "Wtstr",
[Wlitfloat] = "float constant",
[Wlitint] = "int constant",
[Wlitbool] = "bool",
[Wlitstr] = "string",
[Wlitnil] = "nil",
};
int
Wconv(Fmt *fp)
{
char buf[500];
int w;
w = va_arg(fp->args, int);
if(w < 0 || w >= nelem(wnames) || wnames[w] == nil)
return fmtprint(fp, "W-%d", w);
return fmtstrcpy(fp, wnames[w]);
}
int int
isnil(Node *n) isnil(Node *n)
{ {
...@@ -1466,6 +1498,20 @@ out: ...@@ -1466,6 +1498,20 @@ out:
return t; return t;
} }
int
iscomposite(Type *t)
{
if(t == T)
return 0;
switch(t->etype) {
case TMAP:
case TARRAY:
case TSTRUCT:
return 1;
}
return 0;
}
Sym* Sym*
globalsig(Type *t) globalsig(Type *t)
{ {
......
...@@ -521,13 +521,15 @@ loop: ...@@ -521,13 +521,15 @@ loop:
l = n->left; l = n->left;
if(l == N) if(l == N)
goto ret; goto ret;
walktype(l, Erv); walktype(l, Erv);
t = n->type; t = n->type;
if(t == T) if(t == T)
goto ret; goto ret;
convlit(l, t); if(!iscomposite(t))
convlit(l, t);
// nil conversion // nil conversion
if(eqtype(t, l->type, 0)) { if(eqtype(t, l->type, 0)) {
...@@ -589,7 +591,8 @@ loop: ...@@ -589,7 +591,8 @@ loop:
goto ret; goto ret;
} }
badtype(n->op, l->type, t); if(l->type != T)
yyerror("cannot convert %T to %T", l->type, t);
goto ret; goto ret;
case ORETURN: case ORETURN:
......
// errchk $G -e $D/$F.go
// Copyright 2009 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
// explicit conversions are okay, even if they overflow
var x1 = string(1);
var x2 string = string(1);
var x3 = int(1.5);
var x4 int = int(1.5);
var x5 = "a" + string(1);
var x6 = int(1e100);
var x7 = float(1e1000);
// implicit conversions merit scrutiny
var s string;
var bad1 string = 1; // ERROR "conver"
var bad2 = s + 1; // ERROR "conver"
var bad3 = s + 'a'; // ERROR "conver"
var bad4 = "a" + 1; // ERROR "literals"
var bad5 = "a" + 'a'; // ERROR "literals"
var bad6 int = 1.5; // ERROR "convert"
var bad7 int = 1e100; // ERROR "overflow"
var bad8 float = 1e1000; // ERROR "overflow"
// but these implicit conversions are okay
var good1 string = "a";
var good2 int = 1.0;
var good3 int = 1e9;
var good4 float = 1e20;
// errchk $G $D/$F.go
// Copyright 2009 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
var a = []int { "a" }; // ERROR "conver"
var b = int { 1 }; // ERROR "compos"
func main() {
if sys.argc < 1 { } // ERROR "conver"
}
...@@ -41,7 +41,7 @@ if $* >$TMPOUT 2>$TMPERR; then ...@@ -41,7 +41,7 @@ if $* >$TMPOUT 2>$TMPERR; then
exit 1 exit 1
fi fi
cat $TMPOUT $TMPERR > $TMPALL cat $TMPOUT $TMPERR | grep -v '^ ' > $TMPALL
header=0 header=0
echo 0 > $TMPSTAT echo 0 > $TMPSTAT
......
=========== ./convlit.go
BUG: convlit.go fails
BUG: errchk: ./convlit.go: missing expected error message on line 16: 'conver'
BUG: errchk: ./convlit.go: missing expected error message on line 17: 'conver'
BUG: errchk: ./convlit.go: missing expected error message on line 18: 'conver'
BUG: errchk: ./convlit.go: missing expected error message on line 22: 'convert'
BUG: errchk: ./convlit.go: missing expected error message on line 23: 'overflow'
BUG: errchk: ./convlit.go: missing expected error message on line 24: 'overflow'
BUG: errchk: ./convlit.go: unmatched error messages:
==================================================
./convlit.go:8: cannot convert non-integer constant to int32
./convlit.go:11: overflow converting constant to int32
./convlit.go:12: overflow converting constant to float32
./convlit.go:8: cannot convert non-integer constant to int32
./convlit.go:9: cannot convert non-integer constant to int32
./convlit.go:11: overflow converting constant to int32
./convlit.go:12: overflow converting constant to float32
==================================================
=========== ./helloworld.go =========== ./helloworld.go
hello, world hello, world
...@@ -106,7 +125,16 @@ bugs/bug087.go:8: illegal combination of literals LEN 9 ...@@ -106,7 +125,16 @@ bugs/bug087.go:8: illegal combination of literals LEN 9
BUG: fails incorrectly BUG: fails incorrectly
=========== bugs/bug090.go =========== bugs/bug090.go
BUG: compilation succeeds incorrectly bugs/bug090.go:32: cannot convert non-integer constant to int32
bugs/bug090.go:32: illegal types for operand: AS
int32
bugs/bug090.go:34: cannot convert non-integer constant to int32
bugs/bug090.go:34: illegal types for operand: CALL
bool
bugs/bug090.go:40: cannot convert non-integer constant to int32
bugs/bug090.go:40: illegal types for operand: AS
int32
float64
=========== bugs/bug093.go =========== bugs/bug093.go
M M
...@@ -181,14 +209,15 @@ fixedbugs/bug035.go:7: var f redeclared in this block ...@@ -181,14 +209,15 @@ fixedbugs/bug035.go:7: var f redeclared in this block
=========== fixedbugs/bug037.go =========== fixedbugs/bug037.go
fixedbugs/bug037.go:6: vlong: undefined fixedbugs/bug037.go:6: vlong: undefined
fixedbugs/bug037.go:6: fatal error: addvar: n=NAME-s G0 a(1) l(77) t=<T> nil fixedbugs/bug037.go:6: illegal types for operand: AS
undefined
=========== fixedbugs/bug039.go =========== fixedbugs/bug039.go
fixedbugs/bug039.go:6: var x redeclared in this block fixedbugs/bug039.go:6: var x redeclared in this block
previous declaration at fixedbugs/bug039.go:5 previous declaration at fixedbugs/bug039.go:5
=========== fixedbugs/bug049.go =========== fixedbugs/bug049.go
fixedbugs/bug049.go:6: illegal conversion of constant to string fixedbugs/bug049.go:6: illegal conversion of nil to string
=========== fixedbugs/bug050.go =========== fixedbugs/bug050.go
fixedbugs/bug050.go:3: package statement must be first fixedbugs/bug050.go:3: package statement must be first
...@@ -198,7 +227,7 @@ sys.6:1 fixedbugs/bug050.go:3: syntax error near package ...@@ -198,7 +227,7 @@ sys.6:1 fixedbugs/bug050.go:3: syntax error near package
fixedbugs/bug051.go:10: expression must be a constant fixedbugs/bug051.go:10: expression must be a constant
=========== fixedbugs/bug062.go =========== fixedbugs/bug062.go
fixedbugs/bug062.go:6: illegal conversion of constant to string fixedbugs/bug062.go:6: illegal conversion of nil to string
fixedbugs/bug062.go:6: illegal types for operand: AS fixedbugs/bug062.go:6: illegal types for operand: AS
string string
...@@ -216,10 +245,6 @@ broke ...@@ -216,10 +245,6 @@ broke
=========== fixedbugs/bug072.go =========== fixedbugs/bug072.go
fixedbugs/bug072.go:6: bug: undefined fixedbugs/bug072.go:6: bug: undefined
fixedbugs/bug072.go:6: illegal types for operand: CONV
string
fixedbugs/bug072.go:6: illegal types for operand: CONV
string
=========== fixedbugs/bug073.go =========== fixedbugs/bug073.go
fixedbugs/bug073.go:8: illegal types for operand: LSH fixedbugs/bug073.go:8: illegal types for operand: LSH
...@@ -237,7 +262,8 @@ fixedbugs/bug086.go:5: function ends without a return statement ...@@ -237,7 +262,8 @@ fixedbugs/bug086.go:5: function ends without a return statement
=========== fixedbugs/bug091.go =========== fixedbugs/bug091.go
fixedbugs/bug091.go:15: c: undefined fixedbugs/bug091.go:15: c: undefined
fixedbugs/bug091.go:15: fatal error: addvar: n=NAME-i G0 a(1) l(86) t=<T> nil fixedbugs/bug091.go:15: illegal types for operand: AS
undefined
=========== fixedbugs/bug103.go =========== fixedbugs/bug103.go
fixedbugs/bug103.go:8: function requires a return type fixedbugs/bug103.go:8: function requires a return type
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment