aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/c.c13
-rw-r--r--src/c_eval.c8
-rw-r--r--test/17-misc.c20
3 files changed, 31 insertions, 10 deletions
diff --git a/src/c.c b/src/c.c
index 8c43f5f..0877b56 100644
--- a/src/c.c
+++ b/src/c.c
@@ -1461,6 +1461,7 @@ iniwrite(CComp *cm, InitParser *ip, uint off, uint bitsiz, uint bitoff, Type ty,
if (nerror) return;
if (ip->dyn) {
if (ip->ddat.n < off + siz) {
+ /* extending ddata, can only happen for unknown-size arrays */
uint old = ip->ddat.n;
vresize(&ip->ddat, off + siz);
memset(ip->ddat.p + old, 0, ip->ddat.n - old);
@@ -1702,7 +1703,7 @@ designators(InitParser *ip, CComp *cm)
bool some = 0;
for (;;) {
- uint off, bitsiz, bitoff;
+ uint off, bitsiz, bitoff;
uvlong idx = ~0ull;
if (match(cm, &tk, '[')) {
Expr ex = commaexpr(cm);
@@ -1879,8 +1880,9 @@ initializer(CComp *cm, Type *ty, enum evalmode ev, bool globl,
if (!nerror) {
off = objnewdat(sym, sec, globl, siz = typesize(*ty), align = typealign(*ty));
p = sec == Srodata ? objout.rodata.p : objout.data.p;
+ assert(ip->ddat.n <= siz);
memcpy(p + off, ip->ddat.p, ip->ddat.n);
- memset(p + off + ip->ddat.n, 0, typesize(*ty) - ip->ddat.n);
+ memset(p + off + ip->ddat.n, 0, siz - ip->ddat.n);
for (InitReloc *rel = ip->drel; rel; rel = rel->link) {
objreloc(rel->sym, targ_64bit ? REL_ABS64 : REL_ABS32, sec, off + rel->off, rel->addend);
}
@@ -2028,11 +2030,8 @@ buildagg(CComp *cm, enum typetag tt, internstr name, int id)
} else {
bitsiz = ex.i;
if (bitsiz == 0) {
- if (bitftypesiz) {
- bitfbyteoff += bitftypesiz;
- bitfbyteoff = alignup(bitfbyteoff, typealign(decl.ty));
- }
- bitoff = 0;
+ bitsiz = bitftypesiz - bitoff;
+ continue;
} else if (bitftypesiz && bitftypesiz < tysize) {
/* end of previous bitfield */
bitoff = 0;
diff --git a/src/c_eval.c b/src/c_eval.c
index eff7e94..dce1457 100644
--- a/src/c_eval.c
+++ b/src/c_eval.c
@@ -139,7 +139,7 @@ truthy(const Expr *ex)
static bool
unop(Expr *ex, enum evalmode mode)
{
- Expr *sub = ex->sub;
+ Expr *sub = ex->sub, ex2;
if (mode >= EVSTATICINI && ex->t == EDEREF) {
uvlong off;
@@ -175,10 +175,14 @@ unop(Expr *ex, enum evalmode mode)
p = sub->sub[1].s.p, len = sub->sub[1].s.n;
csiz = typesize(typechild(sub->sub[1].ty));
goto StrRead;
+ } else if (ex->ty.t == TYARRAY && eval(sub, mode)) {
+ sub->ty = ex->ty;
+ *ex = *sub;
+ return 1;
} else return 0;
} else if (ex->t == EADDROF) {
assert(ex->ty.t == TYPTR);
- Expr ex2 = staticaddrof(ex->sub, mode);
+ ex2 = staticaddrof(ex->sub, mode);
if (!ex2.t) return 0;
ex2.span = ex->span;
ex2.ty = ex->ty;
diff --git a/test/17-misc.c b/test/17-misc.c
index ffd2470..73f09d1 100644
--- a/test/17-misc.c
+++ b/test/17-misc.c
@@ -1,5 +1,6 @@
/* EXPECT:
-1155497588
+S3 =16, f2@8, q@14
*/
typedef unsigned long long uvlong;
@@ -29,11 +30,26 @@ _Static_assert(!__is_constexpr(fn1(0)), "");
#include <stddef.h>
#include <stdint.h>
struct foo { int *a, b[2]; };
+
+static int g_37[3][5] = {{1,2,3,4,5},{11,12,13,14,15}};
static intptr_t offst[] = {
(long)((struct foo *)0)->b,
(long)&((struct foo *)0)->a,
(long)&((struct foo *)0)->b[1],
- (intptr_t)("12" - 5)
+ (intptr_t)("12" - 5),
+};
+static int *g_131 = &g_37[0][4];
+static int *g_132 = &g_37[1][3];
+static int *g_133 = &g_37[2][0];
+
+#include <stdint.h>
+struct S3 {
+ unsigned f0 : 21;
+ volatile unsigned f1 : 13;
+ unsigned f2;
+ unsigned : 0;
+ short f3 : 13;
+ char q;
};
extern int printf(const char *, ...);
@@ -43,4 +59,6 @@ int main() {
assert(offst[0] == offsetof(struct foo, b));
assert(offst[1] == offsetof(struct foo, a));
assert(offst[2] == offsetof(struct foo, b[1]));
+ assert(*g_131 == 5 && *g_132 == 14 && *g_133 == 0);
+ printf("S3 =%d, f2@%d, q@%d\n", (int)sizeof(struct S3), (int)offsetof(struct S3, f2), (int)offsetof(struct S3, q));
}