Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
54b40372
Commit
54b40372
authored
Aug 05, 2009
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
delay := processing
R=ken OCL=32772 CL=32772
parent
ebdbbe0f
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
227 additions
and
338 deletions
+227
-338
src/Make.conf
src/Make.conf
+1
-1
src/cmd/gc/dcl.c
src/cmd/gc/dcl.c
+77
-0
src/cmd/gc/gen.c
src/cmd/gc/gen.c
+3
-1
src/cmd/gc/go.h
src/cmd/gc/go.h
+2
-1
src/cmd/gc/go.y
src/cmd/gc/go.y
+2
-2
src/cmd/gc/select.c
src/cmd/gc/select.c
+8
-0
src/cmd/gc/subr.c
src/cmd/gc/subr.c
+1
-1
src/cmd/gc/typecheck.c
src/cmd/gc/typecheck.c
+118
-34
src/cmd/gc/walk.c
src/cmd/gc/walk.c
+3
-287
src/run.bash
src/run.bash
+3
-2
test/declbad.go
test/declbad.go
+5
-5
test/fixedbugs/bug030.go
test/fixedbugs/bug030.go
+1
-1
test/fixedbugs/bug035.go
test/fixedbugs/bug035.go
+2
-2
test/fixedbugs/bug103.go
test/fixedbugs/bug103.go
+1
-1
No files found.
src/Make.conf
View file @
54b40372
...
...
@@ -4,7 +4,7 @@
CC
=
quietgcc
LD
=
quietgcc
CFLAGS
=-
ggdb
-
I
$(
GOROOT
)/
include
-
O1
CFLAGS
=-
ggdb
-
I
$(
GOROOT
)/
include
-
O1
-
fno
-
inline
O
=
o
YFLAGS
=-
d
# GNU Make syntax:
...
...
src/cmd/gc/dcl.c
View file @
54b40372
...
...
@@ -574,6 +574,83 @@ dclchecks(void)
}
}
/*
* := declarations
*/
static
int
colasname
(
Node
*
n
)
{
// TODO(rsc): can probably simplify
// once late-binding of names goes in
switch
(
n
->
op
)
{
case
ONAME
:
case
ONONAME
:
case
OPACK
:
case
OTYPE
:
case
OLITERAL
:
return
n
->
sym
!=
S
;
}
return
0
;
}
Node
*
old2new
(
Node
*
n
,
Type
*
t
,
NodeList
**
init
)
{
Node
*
l
;
if
(
!
colasname
(
n
))
{
yyerror
(
"left side of := must be a name"
);
return
n
;
}
if
(
t
!=
T
&&
t
->
funarg
)
{
yyerror
(
"use of multi func value as single value in :="
);
return
n
;
}
l
=
newname
(
n
->
sym
);
dodclvar
(
l
,
t
,
init
);
return
l
;
}
Node
*
colas
(
NodeList
*
left
,
NodeList
*
right
)
{
int
nnew
;
Node
*
n
,
*
as
;
NodeList
*
l
;
if
(
count
(
left
)
==
1
&&
count
(
right
)
==
1
)
as
=
nod
(
OAS
,
left
->
n
,
right
->
n
);
else
{
as
=
nod
(
OAS2
,
N
,
N
);
as
->
list
=
left
;
as
->
rlist
=
right
;
}
as
->
colas
=
1
;
nnew
=
0
;
for
(
l
=
left
;
l
;
l
=
l
->
next
)
{
n
=
l
->
n
;
if
(
!
colasname
(
n
))
{
yyerror
(
"non-name %#N on left side of :="
,
n
);
continue
;
}
if
(
n
->
sym
->
block
==
block
)
continue
;
nnew
++
;
n
=
newname
(
n
->
sym
);
declare
(
n
,
dclcontext
);
if
(
as
->
op
==
OAS
)
as
->
left
=
n
;
n
->
defn
=
as
;
as
->
ninit
=
list
(
as
->
ninit
,
nod
(
ODCL
,
n
,
N
));
l
->
n
=
n
;
}
if
(
nnew
==
0
)
yyerror
(
"no new variables on left side of :="
);
return
as
;
}
/*
* structs, functions, and methods.
...
...
src/cmd/gc/gen.c
View file @
54b40372
...
...
@@ -35,7 +35,9 @@ allocparams(void)
n
=
l
->
n
;
if
(
n
->
op
!=
ONAME
||
n
->
class
!=
PAUTO
)
continue
;
typecheck
(
&
n
,
Erv
);
typecheck
(
&
n
,
Erv
);
// only needed for unused variables
if
(
n
->
type
==
T
)
continue
;
dowidth
(
n
->
type
);
w
=
n
->
type
->
width
;
if
(
n
->
class
&
PHEAP
)
...
...
src/cmd/gc/go.h
View file @
54b40372
...
...
@@ -465,7 +465,8 @@ enum
Etop
=
1
<<
1
,
// evaluated at statement level
Erv
=
1
<<
2
,
// evaluated in value context
Etype
=
1
<<
3
,
Ecall
=
1
<<
4
,
Ecall
=
1
<<
4
,
// call-only expressions are ok
Efnstruct
=
1
<<
5
,
// multivalue function returns are ok
};
#define BITS 5
...
...
src/cmd/gc/go.y
View file @
54b40372
...
...
@@ -519,8 +519,8 @@ case:
//
done
in
casebody
()
poptodcl
();
$$
=
nod
(
OXCASE
,
N
,
N
);
typecheck
(&$
4
,
Erv
);
$$->
list
=
list1
(
nod
(
OAS
,
selectas
($
2
,
$
4
,
&$$->
ninit
),
$
4
));
//
$$->
list
=
list1
(
nod
(
OAS
,
selectas
($
2
,
$
4
,
&$$->
ninit
),
$
4
)
);
$$->
list
=
list1
(
colas
(
list1
($
2
),
list1
($
4
)
));
}
|
LDEFAULT
':'
{
...
...
src/cmd/gc/select.c
View file @
54b40372
...
...
@@ -66,6 +66,10 @@ typecheckselect(Node *sel)
ncase
->
list
=
nil
;
setlineno
(
n
);
switch
(
n
->
op
)
{
default:
yyerror
(
"select case must be receive, send or assign recv"
);;
break
;
case
OAS
:
// convert x = <-c into OSELRECV(x, c)
if
(
n
->
right
->
op
!=
ORECV
)
{
...
...
@@ -123,6 +127,10 @@ walkselect(Node *sel)
r
=
nod
(
OIF
,
N
,
N
);
r
->
nbody
=
ncase
->
ninit
;
ncase
->
ninit
=
nil
;
if
(
n
!=
nil
)
{
r
->
nbody
=
concat
(
r
->
nbody
,
n
->
ninit
);
n
->
ninit
=
nil
;
}
if
(
n
==
nil
)
{
// selectdefault(sel *byte);
r
->
ntest
=
mkcall
(
"selectdefault"
,
types
[
TBOOL
],
&
init
,
var
);
...
...
src/cmd/gc/subr.c
View file @
54b40372
...
...
@@ -582,7 +582,7 @@ dodump(Node *n, int dep)
print
(
"%O-ntype
\n
"
,
n
->
op
);
dodump
(
n
->
ntype
,
dep
+
1
);
}
if
(
n
->
defn
!=
nil
)
{
if
(
n
->
defn
!=
nil
&&
n
->
defn
->
op
!=
OAS
&&
n
->
defn
->
op
!=
OAS2
)
{
indent
(
dep
);
print
(
"%O-defn
\n
"
,
n
->
op
);
dodump
(
n
->
defn
,
dep
+
1
);
...
...
src/cmd/gc/typecheck.c
View file @
54b40372
...
...
@@ -27,6 +27,7 @@ static int nokeys(NodeList*);
static
void
typecheckcomplit
(
Node
**
);
static
void
addrescapes
(
Node
*
);
static
void
typecheckas2
(
Node
*
);
static
void
typecheckas
(
Node
*
);
static
void
checklvalue
(
Node
*
,
char
*
);
static
void
checkassign
(
Node
*
);
static
void
checkassignlist
(
NodeList
*
);
...
...
@@ -88,8 +89,8 @@ reswitch:
case
ONAME
:
if
(
n
->
etype
!=
0
)
{
yyerror
(
"must call builtin %S"
,
n
->
sym
)
;
goto
error
;
ok
|=
Ecall
;
goto
ret
;
}
ok
|=
Erv
;
goto
ret
;
...
...
@@ -348,6 +349,7 @@ reswitch:
* exprs
*/
case
OADDR
:
ok
|=
Erv
;
typecheck
(
&
n
->
left
,
Erv
);
if
(
n
->
left
->
type
==
T
)
goto
error
;
...
...
@@ -368,6 +370,7 @@ reswitch:
goto
ret
;
case
OCOMPLIT
:
ok
|=
Erv
;
typecheckcomplit
(
&
n
);
if
(
n
->
type
==
T
)
goto
error
;
...
...
@@ -403,6 +406,7 @@ reswitch:
goto
ret
;
case
ODOTTYPE
:
ok
|=
Erv
;
typecheck
(
&
n
->
left
,
Erv
);
defaultlit
(
&
n
->
left
,
T
);
l
=
n
->
left
;
...
...
@@ -422,6 +426,7 @@ reswitch:
goto
ret
;
case
OINDEX
:
ok
|=
Erv
;
typecheck
(
&
n
->
left
,
Erv
);
defaultlit
(
&
n
->
left
,
T
);
implicitstar
(
&
n
->
left
);
...
...
@@ -436,21 +441,18 @@ reswitch:
goto
error
;
case
TARRAY
:
ok
|=
Erv
;
defaultlit
(
&
n
->
right
,
types
[
TUINT
]);
n
->
type
=
t
->
type
;
break
;
case
TMAP
:
n
->
etype
=
0
;
ok
|=
Erv
;
defaultlit
(
&
n
->
right
,
t
->
down
);
n
->
type
=
t
->
type
;
n
->
op
=
OINDEXMAP
;
break
;
case
TSTRING
:
ok
|=
Erv
;
defaultlit
(
&
n
->
right
,
types
[
TUINT
]);
n
->
type
=
types
[
TUINT8
];
n
->
op
=
OINDEXSTR
;
...
...
@@ -459,6 +461,7 @@ reswitch:
goto
ret
;
case
ORECV
:
ok
|=
Etop
|
Erv
;
typecheck
(
&
n
->
left
,
Erv
);
defaultlit
(
&
n
->
left
,
T
);
l
=
n
->
left
;
...
...
@@ -473,10 +476,10 @@ reswitch:
goto
error
;
}
n
->
type
=
t
->
type
;
ok
|=
Erv
;
goto
ret
;
case
OSEND
:
ok
|=
Etop
|
Erv
;
l
=
typecheck
(
&
n
->
left
,
Erv
);
typecheck
(
&
n
->
right
,
Erv
);
defaultlit
(
&
n
->
left
,
T
);
...
...
@@ -495,7 +498,6 @@ reswitch:
n
->
etype
=
0
;
if
(
top
&
Erv
)
n
->
op
=
OSENDNB
;
ok
|=
Etop
|
Erv
;
n
->
type
=
types
[
TBOOL
];
goto
ret
;
...
...
@@ -564,7 +566,10 @@ reswitch:
typecheck
(
&
n
->
left
,
Erv
|
Etype
|
Ecall
);
defaultlit
(
&
n
->
left
,
T
);
l
=
n
->
left
;
typechecklist
(
n
->
list
,
Erv
);
if
(
count
(
n
->
list
)
==
1
)
typecheck
(
&
n
->
list
->
n
,
Erv
|
Efnstruct
);
else
typechecklist
(
n
->
list
,
Erv
);
if
((
t
=
l
->
type
)
==
T
)
goto
error
;
dowidth
(
t
);
...
...
@@ -598,12 +603,11 @@ reswitch:
break
;
}
typecheckaste
(
OCALL
,
getinargx
(
t
),
n
->
list
);
if
(
t
->
outtuple
==
0
)
{
ok
|=
Etop
;
ok
|=
Etop
;
if
(
t
->
outtuple
==
0
)
goto
ret
;
}
ok
|=
Erv
;
if
(
t
->
outtuple
==
1
)
{
ok
|=
Erv
;
t
=
getoutargx
(
l
->
type
)
->
type
;
if
(
t
->
etype
==
TFIELD
)
t
=
t
->
type
;
...
...
@@ -611,12 +615,16 @@ reswitch:
goto
ret
;
}
// multiple return
// ok |= Emulti;
if
(
!
(
top
&
(
Efnstruct
|
Etop
)))
{
yyerror
(
"multiple-value %#N() in single-value context"
,
l
);
goto
ret
;
}
n
->
type
=
getoutargx
(
l
->
type
);
goto
ret
;
case
OCAP
:
case
OLEN
:
ok
|=
Erv
;
if
(
onearg
(
n
)
<
0
)
goto
error
;
typecheck
(
&
n
->
left
,
Erv
);
...
...
@@ -671,6 +679,7 @@ reswitch:
case
OCONV
:
doconv:
ok
|=
Erv
;
typecheck
(
&
n
->
left
,
Erv
);
defaultlit
(
&
n
->
left
,
n
->
type
);
if
((
t
=
n
->
left
->
type
)
==
T
||
n
->
type
==
T
)
...
...
@@ -681,6 +690,7 @@ reswitch:
goto
ret
;
case
OMAKE
:
ok
|=
Erv
;
args
=
n
->
list
;
if
(
args
==
nil
)
{
yyerror
(
"missing argument to make"
);
...
...
@@ -779,6 +789,7 @@ reswitch:
goto
ret
;
case
ONEW
:
ok
|=
Erv
;
args
=
n
->
list
;
if
(
args
==
nil
)
{
yyerror
(
"missing argument to new"
);
...
...
@@ -800,6 +811,7 @@ reswitch:
case
OPANICN
:
case
OPRINT
:
case
OPRINTN
:
ok
|=
Etop
;
typechecklist
(
n
->
list
,
Erv
);
goto
ret
;
...
...
@@ -807,14 +819,12 @@ reswitch:
* statements
*/
case
OAS
:
typecheck
(
&
n
->
left
,
Erv
);
checkassign
(
n
->
left
);
typecheck
(
&
n
->
right
,
Erv
);
if
(
n
->
left
->
type
!=
T
&&
n
->
right
&&
n
->
right
->
type
!=
T
)
n
->
right
=
typecheckconv
(
nil
,
n
->
right
,
n
->
left
->
type
,
0
);
ok
|=
Etop
;
typecheckas
(
n
);
goto
ret
;
case
OAS2
:
ok
|=
Etop
;
typecheckas2
(
n
);
goto
ret
;
...
...
@@ -825,14 +835,17 @@ reswitch:
case
OGOTO
:
case
OLABEL
:
case
OXFALL
:
ok
|=
Etop
;
goto
ret
;
case
ODEFER
:
case
OPROC
:
ok
|=
Etop
;
typecheck
(
&
n
->
left
,
Etop
);
goto
ret
;
case
OFOR
:
ok
|=
Etop
;
typechecklist
(
n
->
ninit
,
Etop
);
typecheck
(
&
n
->
ntest
,
Erv
);
if
(
n
->
ntest
!=
N
&&
(
t
=
n
->
ntest
->
type
)
!=
T
&&
t
->
etype
!=
TBOOL
)
...
...
@@ -842,6 +855,7 @@ reswitch:
goto
ret
;
case
OIF
:
ok
|=
Etop
;
typechecklist
(
n
->
ninit
,
Etop
);
typecheck
(
&
n
->
ntest
,
Erv
);
if
(
n
->
ntest
!=
N
&&
(
t
=
n
->
ntest
->
type
)
!=
T
&&
t
->
etype
!=
TBOOL
)
...
...
@@ -851,30 +865,35 @@ reswitch:
goto
ret
;
case
ORETURN
:
typechecklist
(
n
->
list
,
Erv
);
ok
|=
Etop
;
typechecklist
(
n
->
list
,
Erv
|
Efnstruct
);
if
(
curfn
->
type
->
outnamed
&&
n
->
list
==
nil
)
goto
ret
;
typecheckaste
(
ORETURN
,
getoutargx
(
curfn
->
type
),
n
->
list
);
goto
ret
;
case
OSELECT
:
ok
|=
Etop
;
typecheckselect
(
n
);
goto
ret
;
case
OSWITCH
:
ok
|=
Etop
;
typecheckswitch
(
n
);
goto
ret
;
case
OTYPECASE
:
ok
|=
Etop
|
Erv
;
typecheck
(
&
n
->
left
,
Erv
);
ok
|=
Erv
;
goto
ret
;
case
OTYPESW
:
ok
|=
Etop
;
typecheck
(
&
n
->
right
,
Erv
);
goto
ret
;
case
OXCASE
:
ok
|=
Etop
;
typechecklist
(
n
->
list
,
Erv
);
typechecklist
(
n
->
nbody
,
Etop
);
goto
ret
;
...
...
@@ -891,7 +910,15 @@ ret:
goto
error
;
}
if
((
ok
&
Ecall
)
&&
!
(
top
&
Ecall
))
{
yyerror
(
"must call method %#N"
,
n
);
yyerror
(
"must call %#N"
,
n
);
goto
error
;
}
if
((
top
&
(
Ecall
|
Erv
|
Etype
))
&&
!
(
ok
&
(
Erv
|
Etype
|
Ecall
)))
{
yyerror
(
"%#N used as value"
,
n
);
goto
error
;
}
if
((
top
&
Etop
)
&&
!
(
ok
&
Etop
))
{
yyerror
(
"%#N not used"
,
n
);
goto
error
;
}
...
...
@@ -1662,8 +1689,41 @@ checkassignlist(NodeList *l)
}
/*
* multiple assignment
* type check assignment.
* if this assignment is the definition of a var on the left side,
* fill in the var's type.
*/
static
void
typecheckas
(
Node
*
n
)
{
// delicate little dance.
// the definition of n may refer to this assignment
// as its definition, in which case it will call typecheckas.
// in that case, do not call typecheck back, or it will cycle.
// if the variable has a type (ntype) then typechecking
// will not look at defn, so it is okay (and desirable,
// so that the conversion below happens).
if
(
n
->
left
->
defn
!=
n
||
n
->
left
->
ntype
)
typecheck
(
&
n
->
left
,
Erv
);
checkassign
(
n
->
left
);
typecheck
(
&
n
->
right
,
Erv
);
if
(
n
->
left
->
type
!=
T
&&
n
->
right
&&
n
->
right
->
type
!=
T
)
n
->
right
=
typecheckconv
(
nil
,
n
->
right
,
n
->
left
->
type
,
0
);
if
(
n
->
left
->
defn
==
n
&&
n
->
left
->
ntype
==
N
)
{
defaultlit
(
&
n
->
right
,
T
);
n
->
left
->
type
=
n
->
right
->
type
;
}
// second half of dance.
// now that right is done, typecheck the left
// just to get it over with. see dance above.
n
->
typecheck
=
1
;
if
(
n
->
left
->
typecheck
==
0
)
typecheck
(
&
n
->
left
,
Erv
);
}
static
void
typecheckas2
(
Node
*
n
)
{
...
...
@@ -1673,19 +1733,30 @@ typecheckas2(Node *n)
Iter
s
;
Type
*
t
;
typechecklist
(
n
->
list
,
Erv
);
checkassignlist
(
n
->
list
);
typechecklist
(
n
->
rlist
,
Erv
);
for
(
ll
=
n
->
list
;
ll
;
ll
=
ll
->
next
)
{
// delicate little dance.
if
(
ll
->
n
->
defn
!=
n
||
ll
->
n
->
ntype
)
typecheck
(
&
ll
->
n
,
Erv
);
}
cl
=
count
(
n
->
list
);
cr
=
count
(
n
->
rlist
);
checkassignlist
(
n
->
list
);
if
(
cl
>
1
&&
cr
==
1
)
typecheck
(
&
n
->
rlist
->
n
,
Erv
|
Efnstruct
);
else
typechecklist
(
n
->
rlist
,
Erv
);
if
(
cl
==
cr
)
{
// easy
for
(
ll
=
n
->
list
,
lr
=
n
->
rlist
;
ll
;
ll
=
ll
->
next
,
lr
=
lr
->
next
)
for
(
ll
=
n
->
list
,
lr
=
n
->
rlist
;
ll
;
ll
=
ll
->
next
,
lr
=
lr
->
next
)
{
if
(
ll
->
n
->
type
!=
T
&&
lr
->
n
->
type
!=
T
)
lr
->
n
=
typecheckconv
(
nil
,
lr
->
n
,
ll
->
n
->
type
,
0
);
return
;
if
(
ll
->
n
->
defn
==
n
&&
ll
->
n
->
ntype
==
N
)
{
defaultlit
(
&
lr
->
n
,
T
);
ll
->
n
->
type
=
lr
->
n
->
type
;
}
}
goto
out
;
}
...
...
@@ -1695,18 +1766,18 @@ typecheckas2(Node *n)
// m[i] = x, ok
if
(
cl
==
1
&&
cr
==
2
&&
l
->
op
==
OINDEXMAP
)
{
if
(
l
->
type
==
T
)
return
;
goto
out
;
n
->
op
=
OAS2MAPW
;
n
->
rlist
->
n
=
typecheckconv
(
nil
,
r
,
l
->
type
->
down
,
0
);
r
=
n
->
rlist
->
next
->
n
;
n
->
rlist
->
next
->
n
=
typecheckconv
(
nil
,
r
,
types
[
TBOOL
],
0
);
return
;
goto
out
;
}
// x,y,z = f()
if
(
cr
==
1
)
{
if
(
r
->
type
==
T
)
return
;
goto
out
;
switch
(
r
->
op
)
{
case
OCALLMETH
:
case
OCALLINTER
:
...
...
@@ -1722,16 +1793,18 @@ typecheckas2(Node *n)
if
(
ll
->
n
->
type
!=
T
)
if
(
checkconv
(
t
->
type
,
ll
->
n
->
type
,
0
,
&
op
,
&
et
)
<
0
)
yyerror
(
"cannot assign type %T to %+N"
,
t
->
type
,
ll
->
n
);
if
(
ll
->
n
->
defn
==
n
&&
ll
->
n
->
ntype
==
N
)
ll
->
n
->
type
=
t
->
type
;
t
=
structnext
(
&
s
);
}
return
;
goto
out
;
}
}
// x, ok = y
if
(
cl
==
2
&&
cr
==
1
)
{
if
(
r
->
type
==
T
)
return
;
goto
out
;
switch
(
r
->
op
)
{
case
OINDEXMAP
:
n
->
op
=
OAS2MAPR
;
...
...
@@ -1744,13 +1817,24 @@ typecheckas2(Node *n)
common:
if
(
l
->
type
!=
T
&&
checkconv
(
r
->
type
,
l
->
type
,
0
,
&
op
,
&
et
)
<
0
)
yyerror
(
"cannot assign %+N to %+N"
,
r
,
l
);
if
(
l
->
defn
==
n
)
l
->
type
=
r
->
type
;
l
=
n
->
list
->
next
->
n
;
if
(
l
->
type
!=
T
&&
checkconv
(
types
[
TBOOL
],
l
->
type
,
0
,
&
op
,
&
et
)
<
0
)
yyerror
(
"cannot assign bool value to %+N"
,
l
);
return
;
if
(
l
->
defn
==
n
&&
l
->
ntype
==
N
)
l
->
type
=
types
[
TBOOL
];
goto
out
;
}
}
mismatch:
yyerror
(
"assignment count mismatch: %d = %d"
,
cl
,
cr
);
out:
// second half of dance
n
->
typecheck
=
1
;
for
(
ll
=
n
->
list
;
ll
;
ll
=
ll
->
next
)
if
(
ll
->
n
->
typecheck
==
0
)
typecheck
(
&
ll
->
n
,
Erv
);
}
src/cmd/gc/walk.c
View file @
54b40372
...
...
@@ -145,7 +145,6 @@ walkdef(Node *n)
if
(
n
->
type
!=
T
||
n
->
sym
==
S
)
// builtin or no name
goto
ret
;
init
=
nil
;
switch
(
n
->
op
)
{
case
OLITERAL
:
...
...
@@ -185,25 +184,12 @@ walkdef(Node *n)
n
->
diag
=
1
;
goto
ret
;
}
n
->
ntype
=
N
;
}
if
(
n
->
type
!=
T
)
break
;
if
(
n
->
defn
==
N
)
fatal
(
"var without type, init: %S"
,
n
->
sym
);
switch
(
n
->
defn
->
op
)
{
default:
fatal
(
"walkdef name defn"
);
case
OAS
:
typecheck
(
&
n
->
defn
->
right
,
Erv
);
defaultlit
(
&
n
->
defn
->
right
,
T
);
if
((
t
=
n
->
defn
->
right
->
type
)
==
T
)
{
n
->
diag
=
1
;
goto
ret
;
}
n
->
type
=
t
;
break
;
}
typecheck
(
&
n
->
defn
,
Etop
);
// fills in n->type
break
;
}
...
...
@@ -1667,7 +1653,7 @@ ifacecvt(Type *tl, Node *n, int et, NodeList **init)
r
=
nod
(
OCALL
,
on
,
N
);
r
->
list
=
args
;
typecheck
(
&
r
,
Erv
);
typecheck
(
&
r
,
Erv
|
Efnstruct
);
walkexpr
(
&
r
,
init
);
return
r
;
}
...
...
@@ -1716,276 +1702,6 @@ out:
return
n
;
}
int
colasname
(
Node
*
n
)
{
// TODO(rsc): can probably simplify
// once late-binding of names goes in
switch
(
n
->
op
)
{
case
ONAME
:
case
ONONAME
:
case
OPACK
:
break
;
case
OTYPE
:
case
OLITERAL
:
if
(
n
->
sym
!=
S
)
break
;
// fallthrough
default:
return
0
;
}
return
1
;
}
Node
*
old2new
(
Node
*
n
,
Type
*
t
,
NodeList
**
init
)
{
Node
*
l
;
if
(
!
colasname
(
n
))
{
yyerror
(
"left side of := must be a name"
);
return
n
;
}
if
(
t
!=
T
&&
t
->
funarg
)
{
yyerror
(
"use of multi func value as single value in :="
);
return
n
;
}
l
=
newname
(
n
->
sym
);
dodclvar
(
l
,
t
,
init
);
return
l
;
}
static
Node
*
mixedoldnew
(
Node
*
n
,
Type
*
t
)
{
n
=
nod
(
OXXX
,
n
,
N
);
n
->
type
=
t
;
return
n
;
}
static
NodeList
*
checkmixed
(
NodeList
*
nl
,
NodeList
**
init
)
{
Node
*
a
,
*
l
;
NodeList
*
ll
,
*
n
;
Type
*
t
;
int
ntot
,
nred
;
// first pass, check if it is a special
// case of new and old declarations
ntot
=
0
;
// number assignments
nred
=
0
;
// number redeclarations
for
(
ll
=
nl
;
ll
;
ll
=
ll
->
next
)
{
l
=
ll
->
n
;
t
=
l
->
type
;
l
=
l
->
left
;
if
(
!
colasname
(
l
))
goto
allnew
;
if
(
l
->
sym
->
block
==
block
)
nred
++
;
ntot
++
;
}
// test for special case
// a) multi-assignment (ntot>1)
// b) at least one redeclaration (red>0)
// c) not all redeclarations (nred!=ntot)
if
(
nred
==
0
||
ntot
<=
1
||
nred
==
ntot
)
goto
allnew
;
n
=
nil
;
for
(
ll
=
nl
;
ll
;
ll
=
ll
->
next
)
{
l
=
ll
->
n
;
t
=
l
->
type
;
l
=
l
->
left
;
a
=
l
;
if
(
l
->
sym
->
block
!=
block
)
a
=
old2new
(
l
,
t
,
init
);
n
=
list
(
n
,
a
);
}
return
n
;
allnew:
// same as original
n
=
nil
;
for
(
ll
=
nl
;
ll
;
ll
=
ll
->
next
)
{
l
=
ll
->
n
;
t
=
l
->
type
;
l
=
l
->
left
;
a
=
old2new
(
l
,
t
,
init
);
n
=
list
(
n
,
a
);
}
return
n
;
}
Node
*
colas
(
NodeList
*
ll
,
NodeList
*
lr
)
{
Node
*
l
,
*
r
,
*
a
,
*
nl
,
*
nr
;
Iter
savet
;
NodeList
*
init
,
*
savel
,
*
saver
,
*
n
;
Type
*
t
;
int
cl
,
cr
;
/* nl is an expression list.
* nr is an expression list.
* return a newname-list from
* types derived from the rhs.
*/
cr
=
count
(
lr
);
cl
=
count
(
ll
);
init
=
nil
;
n
=
nil
;
/* check calls early, to give better message for a := f() */
if
(
cr
==
1
)
{
nr
=
lr
->
n
;
switch
(
nr
->
op
)
{
case
OCALL
:
case
OCALLFUNC
:
if
(
nr
->
left
->
op
==
ONAME
&&
nr
->
left
->
etype
!=
0
)
break
;
typecheck
(
&
nr
->
left
,
Erv
|
Etype
|
Ecall
);
walkexpr
(
&
nr
->
left
,
&
init
);
if
(
nr
->
left
->
op
==
OTYPE
)
break
;
goto
call
;
case
OCALLMETH
:
case
OCALLINTER
:
typecheck
(
&
nr
->
left
,
Erv
);
walkexpr
(
&
nr
->
left
,
&
init
);
call:
convlit
(
&
nr
->
left
,
types
[
TFUNC
]);
t
=
nr
->
left
->
type
;
if
(
t
==
T
)
goto
outl
;
// error already printed
if
(
t
->
etype
==
tptr
)
t
=
t
->
type
;
if
(
t
==
T
||
t
->
etype
!=
TFUNC
)
{
yyerror
(
"cannot call %T"
,
t
);
goto
outl
;
}
if
(
t
->
outtuple
!=
cl
)
{
cr
=
t
->
outtuple
;
goto
badt
;
}
// finish call - first half above
t
=
structfirst
(
&
savet
,
getoutarg
(
t
));
if
(
t
==
T
)
goto
outl
;
for
(
savel
=
ll
;
savel
;
savel
=
savel
->
next
)
{
l
=
savel
->
n
;
a
=
mixedoldnew
(
l
,
t
->
type
);
n
=
list
(
n
,
a
);
t
=
structnext
(
&
savet
);
}
n
=
checkmixed
(
n
,
&
init
);
goto
out
;
}
}
if
(
cl
!=
cr
)
{
if
(
cr
==
1
)
{
nr
=
lr
->
n
;
goto
multi
;
}
goto
badt
;
}
for
(
savel
=
ll
,
saver
=
lr
;
savel
!=
nil
;
savel
=
savel
->
next
,
saver
=
saver
->
next
)
{
l
=
savel
->
n
;
r
=
saver
->
n
;
typecheck
(
&
r
,
Erv
);
defaultlit
(
&
r
,
T
);
saver
->
n
=
r
;
a
=
mixedoldnew
(
l
,
r
->
type
);
n
=
list
(
n
,
a
);
}
n
=
checkmixed
(
n
,
&
init
);
goto
out
;
multi:
typecheck
(
&
nr
,
Erv
);
lr
->
n
=
nr
;
/*
* there is a list on the left
* and a mono on the right.
* go into the right to get
* individual types for the left.
*/
switch
(
nr
->
op
)
{
default:
goto
badt
;
case
OINDEXMAP
:
// check if rhs is a map index.
// if so, types are valuetype,bool
if
(
cl
!=
2
)
goto
badt
;
walkexpr
(
&
nr
->
left
,
&
init
);
t
=
nr
->
left
->
type
;
a
=
mixedoldnew
(
ll
->
n
,
t
->
type
);
n
=
list1
(
a
);
a
=
mixedoldnew
(
ll
->
next
->
n
,
types
[
TBOOL
]);
n
=
list
(
n
,
a
);
n
=
checkmixed
(
n
,
&
init
);
break
;
case
ODOTTYPE
:
// a,b := i.(T)
walkdottype
(
nr
,
&
init
);
if
(
cl
!=
2
)
goto
badt
;
// a,b = iface
a
=
mixedoldnew
(
ll
->
n
,
nr
->
type
);
n
=
list1
(
a
);
a
=
mixedoldnew
(
ll
->
next
->
n
,
types
[
TBOOL
]);
n
=
list
(
n
,
a
);
n
=
checkmixed
(
n
,
&
init
);
break
;
case
ORECV
:
if
(
cl
!=
2
)
goto
badt
;
walkexpr
(
&
nr
->
left
,
&
init
);
t
=
nr
->
left
->
type
;
if
(
!
istype
(
t
,
TCHAN
))
goto
badt
;
a
=
mixedoldnew
(
ll
->
n
,
t
->
type
);
n
=
list1
(
a
);
a
=
mixedoldnew
(
ll
->
next
->
n
,
types
[
TBOOL
]);
n
=
list
(
n
,
a
);
n
=
checkmixed
(
n
,
&
init
);
break
;
}
goto
out
;
badt:
nl
=
ll
->
n
;
if
(
nl
->
diag
==
0
)
{
nl
->
diag
=
1
;
yyerror
(
"assignment count mismatch: %d = %d %#N"
,
cl
,
cr
,
lr
->
n
);
}
outl:
n
=
ll
;
out:
// n is the lhs of the assignment.
// init holds the list of declarations.
a
=
nod
(
OAS2
,
N
,
N
);
a
->
list
=
n
;
a
->
rlist
=
lr
;
a
->
ninit
=
init
;
a
->
colas
=
1
;
return
a
;
}
/*
* rewrite a range statement
* k and v are names/new_names
...
...
@@ -2596,7 +2312,7 @@ vmkcall(Node *fn, Type *t, NodeList **init, va_list va)
r
=
nod
(
OCALL
,
fn
,
N
);
r
->
list
=
args
;
if
(
fn
->
type
->
outtuple
>
0
)
typecheck
(
&
r
,
Erv
);
typecheck
(
&
r
,
Erv
|
Efnstruct
);
else
typecheck
(
&
r
,
Etop
);
walkexpr
(
&
r
,
init
);
...
...
src/run.bash
View file @
54b40372
...
...
@@ -16,8 +16,9 @@ maketest() {
do
(
xcd
$i
make clean
time
make
# make clean
# time make
make
install
make
test
)
||
exit
$?
done
...
...
test/declbad.go
View file @
54b40372
...
...
@@ -16,7 +16,7 @@ func main() {
{
// simple redeclaration
i
:=
f1
();
i
:=
f1
();
// ERROR "redeclared|redefinition"
i
:=
f1
();
// ERROR "redeclared|redefinition
|no new
"
}
{
// change of type for f
...
...
@@ -31,21 +31,21 @@ func main() {
{
// no new variables
i
,
f
,
s
:=
f3
();
i
,
f
:=
f2
();
// ERROR "redeclared|redefinition"
i
,
f
:=
f2
();
// ERROR "redeclared|redefinition
|no new
"
}
{
// single redeclaration
i
,
f
,
s
:=
f3
();
// GCCGO_ERROR "previous"
i
:=
f1
();
// ERROR "redeclared|redefinition"
i
:=
f1
();
// ERROR "redeclared|redefinition
|no new
"
}
// double redeclaration
{
i
,
f
,
s
:=
f3
();
i
,
f
:=
f2
();
// ERROR "redeclared|redefinition"
i
,
f
:=
f2
();
// ERROR "redeclared|redefinition
|no new
"
}
{
// triple redeclaration
i
,
f
,
s
:=
f3
();
i
,
f
,
s
:=
f3
();
// ERROR "redeclared|redefinition"
i
,
f
,
s
:=
f3
();
// ERROR "redeclared|redefinition
|no new
"
}
}
test/fixedbugs/bug030.go
View file @
54b40372
...
...
@@ -8,5 +8,5 @@ package main
func
main
()
{
var
x
int
;
x
:=
0
;
//
BUG: redeclaration - should not compile
x
:=
0
;
//
ERROR "declar|:="
}
test/fixedbugs/bug035.go
View file @
54b40372
...
...
@@ -7,7 +7,7 @@
package
main
func
f9
(
a
int
)
(
i
int
,
f
float
)
{
i
:=
9
;
// ERROR "redecl"
f
:=
float
(
9
);
// ERROR "redecl"
i
:=
9
;
// ERROR "redecl
|no new
"
f
:=
float
(
9
);
// ERROR "redecl
|no new
"
return
i
,
f
;
}
test/fixedbugs/bug103.go
View file @
54b40372
...
...
@@ -9,6 +9,6 @@ package main
func
f
()
/* no return type */
{}
func
main
()
{
x
:=
f
();
// ERROR "mismatch"
x
:=
f
();
// ERROR "mismatch
|as value
"
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment