mirror of
https://github.com/golang/go
synced 2024-11-25 05:57:57 -07:00
gc: zero-width struct, zero-length array fixes
Fixes #1774. Fixes #2095. Fixes #2097. R=ken2 CC=golang-dev https://golang.org/cl/4826046
This commit is contained in:
parent
dec8009fe8
commit
a84abbe508
@ -595,9 +595,6 @@ agen(Node *n, Node *res)
|
|||||||
// i is in &n1 (if not constant)
|
// i is in &n1 (if not constant)
|
||||||
// w is width
|
// w is width
|
||||||
|
|
||||||
if(w == 0)
|
|
||||||
fatal("index is zero width");
|
|
||||||
|
|
||||||
// constant index
|
// constant index
|
||||||
if(isconst(nr, CTINT)) {
|
if(isconst(nr, CTINT)) {
|
||||||
if(isconst(nl, CTSTR))
|
if(isconst(nl, CTSTR))
|
||||||
@ -683,7 +680,9 @@ agen(Node *n, Node *res)
|
|||||||
gmove(&n1, &n3);
|
gmove(&n1, &n3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(w == 1 || w == 2 || w == 4 || w == 8) {
|
if(w == 0) {
|
||||||
|
// nothing to do
|
||||||
|
} else if(w == 1 || w == 2 || w == 4 || w == 8) {
|
||||||
memset(&n4, 0, sizeof n4);
|
memset(&n4, 0, sizeof n4);
|
||||||
n4.op = OADDR;
|
n4.op = OADDR;
|
||||||
n4.left = &n2;
|
n4.left = &n2;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
int thechar = '5';
|
int thechar = '5';
|
||||||
char* thestring = "arm";
|
char* thestring = "arm";
|
||||||
|
|
||||||
|
vlong MAXWIDTH = (1LL<<32) - 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* go declares several platform-specific type aliases:
|
* go declares several platform-specific type aliases:
|
||||||
|
@ -510,9 +510,6 @@ agen(Node *n, Node *res)
|
|||||||
regfree(&n4);
|
regfree(&n4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(w == 0)
|
|
||||||
fatal("index is zero width");
|
|
||||||
|
|
||||||
// constant index
|
// constant index
|
||||||
if(isconst(nr, CTINT)) {
|
if(isconst(nr, CTINT)) {
|
||||||
if(isconst(nl, CTSTR))
|
if(isconst(nl, CTSTR))
|
||||||
@ -600,7 +597,9 @@ agen(Node *n, Node *res)
|
|||||||
gmove(&n1, &n3);
|
gmove(&n1, &n3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(w == 1 || w == 2 || w == 4 || w == 8) {
|
if(w == 0) {
|
||||||
|
// nothing to do
|
||||||
|
} else if(w == 1 || w == 2 || w == 4 || w == 8) {
|
||||||
p1 = gins(ALEAQ, &n2, &n3);
|
p1 = gins(ALEAQ, &n2, &n3);
|
||||||
p1->from.scale = w;
|
p1->from.scale = w;
|
||||||
p1->from.index = p1->from.type;
|
p1->from.index = p1->from.type;
|
||||||
@ -608,7 +607,6 @@ agen(Node *n, Node *res)
|
|||||||
} else {
|
} else {
|
||||||
ginscon(optoas(OMUL, t), w, &n2);
|
ginscon(optoas(OMUL, t), w, &n2);
|
||||||
gins(optoas(OADD, types[tptr]), &n2, &n3);
|
gins(optoas(OADD, types[tptr]), &n2, &n3);
|
||||||
gmove(&n3, res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
indexdone:
|
indexdone:
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
int thechar = '6';
|
int thechar = '6';
|
||||||
char* thestring = "amd64";
|
char* thestring = "amd64";
|
||||||
|
|
||||||
|
vlong MAXWIDTH = 1LL<<50;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* go declares several platform-specific type aliases:
|
* go declares several platform-specific type aliases:
|
||||||
|
@ -562,9 +562,6 @@ agen(Node *n, Node *res)
|
|||||||
regfree(&n4);
|
regfree(&n4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(w == 0)
|
|
||||||
fatal("index is zero width");
|
|
||||||
|
|
||||||
// constant index
|
// constant index
|
||||||
if(isconst(nr, CTINT)) {
|
if(isconst(nr, CTINT)) {
|
||||||
if(isconst(nl, CTSTR))
|
if(isconst(nl, CTSTR))
|
||||||
@ -639,7 +636,9 @@ agen(Node *n, Node *res)
|
|||||||
gmove(&n1, &n3);
|
gmove(&n1, &n3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(w == 1 || w == 2 || w == 4 || w == 8) {
|
if(w == 0) {
|
||||||
|
// nothing to do
|
||||||
|
} else if(w == 1 || w == 2 || w == 4 || w == 8) {
|
||||||
p1 = gins(ALEAL, &n2, &n3);
|
p1 = gins(ALEAL, &n2, &n3);
|
||||||
p1->from.scale = w;
|
p1->from.scale = w;
|
||||||
p1->from.index = p1->from.type;
|
p1->from.index = p1->from.type;
|
||||||
@ -648,7 +647,6 @@ agen(Node *n, Node *res)
|
|||||||
nodconst(&n1, types[TUINT32], w);
|
nodconst(&n1, types[TUINT32], w);
|
||||||
gins(optoas(OMUL, types[TUINT32]), &n1, &n2);
|
gins(optoas(OMUL, types[TUINT32]), &n1, &n2);
|
||||||
gins(optoas(OADD, types[tptr]), &n2, &n3);
|
gins(optoas(OADD, types[tptr]), &n2, &n3);
|
||||||
gmove(&n3, res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
indexdone:
|
indexdone:
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
int thechar = '8';
|
int thechar = '8';
|
||||||
char* thestring = "386";
|
char* thestring = "386";
|
||||||
|
|
||||||
|
vlong MAXWIDTH = (1LL<<32) - 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* go declares several platform-specific type aliases:
|
* go declares several platform-specific type aliases:
|
||||||
|
@ -30,14 +30,18 @@ offmod(Type *t)
|
|||||||
o = 0;
|
o = 0;
|
||||||
for(f=t->type; f!=T; f=f->down) {
|
for(f=t->type; f!=T; f=f->down) {
|
||||||
if(f->etype != TFIELD)
|
if(f->etype != TFIELD)
|
||||||
fatal("widstruct: not TFIELD: %lT", f);
|
fatal("offmod: not TFIELD: %lT", f);
|
||||||
f->width = o;
|
f->width = o;
|
||||||
o += widthptr;
|
o += widthptr;
|
||||||
|
if(o >= MAXWIDTH) {
|
||||||
|
yyerror("interface too large");
|
||||||
|
o = widthptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32
|
static vlong
|
||||||
widstruct(Type *t, uint32 o, int flag)
|
widstruct(Type *errtype, Type *t, vlong o, int flag)
|
||||||
{
|
{
|
||||||
Type *f;
|
Type *f;
|
||||||
int32 w, maxalign;
|
int32 w, maxalign;
|
||||||
@ -69,6 +73,10 @@ widstruct(Type *t, uint32 o, int flag)
|
|||||||
f->nname->xoffset = o;
|
f->nname->xoffset = o;
|
||||||
}
|
}
|
||||||
o += w;
|
o += w;
|
||||||
|
if(o >= MAXWIDTH) {
|
||||||
|
yyerror("type %lT too large", errtype);
|
||||||
|
o = 8; // small but nonzero
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// final width is rounded
|
// final width is rounded
|
||||||
if(flag)
|
if(flag)
|
||||||
@ -226,10 +234,7 @@ dowidth(Type *t)
|
|||||||
|
|
||||||
dowidth(t->type);
|
dowidth(t->type);
|
||||||
if(t->type->width != 0) {
|
if(t->type->width != 0) {
|
||||||
if(tptr == TPTR32)
|
cap = (MAXWIDTH-1) / t->type->width;
|
||||||
cap = ((uint32)-1) / t->type->width;
|
|
||||||
else
|
|
||||||
cap = ((uint64)-1) / t->type->width;
|
|
||||||
if(t->bound > cap)
|
if(t->bound > cap)
|
||||||
yyerror("type %lT larger than address space", t);
|
yyerror("type %lT larger than address space", t);
|
||||||
}
|
}
|
||||||
@ -250,7 +255,7 @@ dowidth(Type *t)
|
|||||||
case TSTRUCT:
|
case TSTRUCT:
|
||||||
if(t->funarg)
|
if(t->funarg)
|
||||||
fatal("dowidth fn struct %T", t);
|
fatal("dowidth fn struct %T", t);
|
||||||
w = widstruct(t, 0, 1);
|
w = widstruct(t, t, 0, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TFUNC:
|
case TFUNC:
|
||||||
@ -268,9 +273,9 @@ dowidth(Type *t)
|
|||||||
// function is 3 cated structures;
|
// function is 3 cated structures;
|
||||||
// compute their widths as side-effect.
|
// compute their widths as side-effect.
|
||||||
t1 = t->type;
|
t1 = t->type;
|
||||||
w = widstruct(*getthis(t1), 0, 0);
|
w = widstruct(t->type, *getthis(t1), 0, 0);
|
||||||
w = widstruct(*getinarg(t1), w, widthptr);
|
w = widstruct(t->type, *getinarg(t1), w, widthptr);
|
||||||
w = widstruct(*getoutarg(t1), w, widthptr);
|
w = widstruct(t->type, *getoutarg(t1), w, widthptr);
|
||||||
t1->argwid = w;
|
t1->argwid = w;
|
||||||
if(w%widthptr)
|
if(w%widthptr)
|
||||||
warn("bad type %T %d\n", t1, w);
|
warn("bad type %T %d\n", t1, w);
|
||||||
|
@ -43,9 +43,10 @@ enum
|
|||||||
AMEMWORD,
|
AMEMWORD,
|
||||||
|
|
||||||
BADWIDTH = -1000000000,
|
BADWIDTH = -1000000000,
|
||||||
MAXWIDTH = 1<<30
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern vlong MAXWIDTH;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* note this is the representation
|
* note this is the representation
|
||||||
* of the compilers string literals,
|
* of the compilers string literals,
|
||||||
|
@ -20,7 +20,7 @@ runtime·makeslice(SliceType *t, int64 len, int64 cap, Slice ret)
|
|||||||
{
|
{
|
||||||
if(len < 0 || (int32)len != len)
|
if(len < 0 || (int32)len != len)
|
||||||
runtime·panicstring("makeslice: len out of range");
|
runtime·panicstring("makeslice: len out of range");
|
||||||
if(cap < len || (int32)cap != cap || cap > ((uintptr)-1) / t->elem->size)
|
if(cap < len || (int32)cap != cap || t->elem->size > 0 && cap > ((uintptr)-1) / t->elem->size)
|
||||||
runtime·panicstring("makeslice: cap out of range");
|
runtime·panicstring("makeslice: cap out of range");
|
||||||
|
|
||||||
makeslice1(t, len, cap, &ret);
|
makeslice1(t, len, cap, &ret);
|
||||||
|
@ -47,15 +47,6 @@ func bigcap() {
|
|||||||
g1 = make([]int, 10, big)
|
g1 = make([]int, 10, big)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
addrBits = 8*uint(unsafe.Sizeof((*byte)(nil)))
|
|
||||||
sh = addrBits/2 - 2
|
|
||||||
)
|
|
||||||
var g2 [][1<<sh][1<<sh]byte
|
|
||||||
func overflow() {
|
|
||||||
g2 = make([][1<<sh][1<<sh]byte, 64)
|
|
||||||
}
|
|
||||||
|
|
||||||
var g3 map[int]int
|
var g3 map[int]int
|
||||||
func badmapcap() {
|
func badmapcap() {
|
||||||
g3 = make(map[int]int, minus1)
|
g3 = make(map[int]int, minus1)
|
||||||
@ -74,6 +65,8 @@ func bigchancap() {
|
|||||||
g4 = make(chan int, big)
|
g4 = make(chan int, big)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const addrBits = unsafe.Sizeof((*byte)(nil))
|
||||||
|
|
||||||
var g5 chan [1<<15]byte
|
var g5 chan [1<<15]byte
|
||||||
func overflowchan() {
|
func overflowchan() {
|
||||||
if addrBits == 32 {
|
if addrBits == 32 {
|
||||||
@ -92,7 +85,6 @@ func main() {
|
|||||||
shouldfail(badcap, "badcap")
|
shouldfail(badcap, "badcap")
|
||||||
shouldfail(badcap1, "badcap1")
|
shouldfail(badcap1, "badcap1")
|
||||||
shouldfail(bigcap, "bigcap")
|
shouldfail(bigcap, "bigcap")
|
||||||
shouldfail(overflow, "overflow")
|
|
||||||
shouldfail(badmapcap, "badmapcap")
|
shouldfail(badmapcap, "badmapcap")
|
||||||
shouldfail(bigmapcap, "bigmapcap")
|
shouldfail(bigmapcap, "bigmapcap")
|
||||||
shouldfail(badchancap, "badchancap")
|
shouldfail(badchancap, "badchancap")
|
||||||
|
19
test/fixedbugs/bug352.go
Normal file
19
test/fixedbugs/bug352.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: bug352
|
||||||
|
|
||||||
|
// Copyright 2011 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 x [10][0]byte
|
||||||
|
var y = make([]struct{}, 10)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if &x[1] != &x[2] {
|
||||||
|
println("BUG: bug352 [0]byte")
|
||||||
|
}
|
||||||
|
if &y[1] != &y[2] {
|
||||||
|
println("BUG: bug352 struct{}")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user