cc: set unspecified elements to zero in local variable initializers

the compiler used to skip zero initialization when initializer
list was given not covering unspecified elements. now we zero
all non explicitely initialized elements. for example:

typedef struct F F;
struct F
{
	int a;
	int b;
	int c;
};

void
main(void)
{
	char a[16] = { 1, 2, 3 };	/* a[3..15] initialized to zero */
	F f = { .b = 1 };			/* f.a, f.c initialized to zero */
}
This commit is contained in:
cinap_lenrek 2015-05-26 19:25:06 +02:00
parent cfafa67640
commit d6a91e0ae4

View file

@ -1542,6 +1542,48 @@ symadjust(Sym *s, Node *n, long del)
}
}
static int
covered1(long o, Node *n)
{
if(n->op == OLIST)
return covered1(o, n->left) || covered1(o, n->right);
if(n->op == OASI)
return covered1(o, n->left);
if(n->op != ONAME)
return 0;
return o >= n->xoffset && o < n->xoffset+n->type->width;
}
static int
covered(long o, long w, Node *n)
{
while(w > 0 && covered1(o, n)) {
o++;
w--;
}
return w == 0;
}
static Node*
initz(Node *q, Type *t, long o, Node *n)
{
Node *p;
if(covered(o, t->width, n))
return n;
p = new(ONAME, Z, Z);
*p = *q;
p->type = t;
p->xoffset = o;
q = new(OCONST, Z, Z);
q->vconst = 0;
q->type = t;
return new(OLIST, new(OASI, p, q), n);
}
Node*
contig(Sym *s, Node *n, long v)
{
@ -1573,12 +1615,6 @@ contig(Sym *s, Node *n, long v)
}
if(n->op == OAS)
diag(Z, "oops in contig");
/*ZZZ this appears incorrect
need to check if the list completely covers the data.
if not, bail
*/
if(n->op == OLIST)
goto no;
if(n->op == OASI)
if(n->left->type)
if(n->left->type->width == w)
@ -1590,46 +1626,28 @@ if not, bail
v = s->offset;
/* unaligned front */
while(w > 0 && (v % ewidth[TIND]) != 0){
p = new(ONAME, Z, Z);
*p = *q;
while(w > 0 && (v % ewidth[TIND]) != 0) {
zt = types[TCHAR];
if(w >= ewidth[TLONG] && (v % ewidth[TLONG]) == 0)
p->type = types[TLONG];
else
p->type = types[TCHAR];
zt = types[TLONG];
n = initz(q, zt, v, n);
v += zt->width;
w -= zt->width;
}
p->xoffset = v;
v += p->type->width;
w -= p->type->width;
m = new(OCONST, Z, Z);
m->vconst = 0;
m->type = p->type;
r = new(OAS, p, m);
n = new(OLIST, r, n);
/* skip initialized words */
while(w >= ewidth[TIND] && covered(v, ewidth[TIND], n)) {
v += ewidth[TIND];
w -= ewidth[TIND];
}
/* unaligned (or small) back */
while(w > 0 && ((w % ewidth[TIND]) != 0 || w <= 16)){
p = new(ONAME, Z, Z);
*p = *q;
while(w > 0 && ((w % ewidth[TIND]) != 0 || w <= 16)) {
zt = types[TCHAR];
if(w >= ewidth[TLONG] && (w % ewidth[TLONG]) == 0)
p->type = types[TLONG];
else
p->type = types[TCHAR];
w -= p->type->width;
p->xoffset = v + w;
m = new(OCONST, Z, Z);
m->vconst = 0;
m->type = p->type;
r = new(OAS, p, m);
n = new(OLIST, r, n);
zt = types[TLONG];
w -= zt->width;
n = initz(q, zt, v + w, n);
}
if(w == 0)