aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/parse.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-19 06:50:12 +0200
committerlemon <lsof@mailbox.org>2022-08-19 06:50:12 +0200
commit01969818aec859611ca1989783b6e0d7f81bdf9e (patch)
tree80324a21b5b4647107d6596eaabd741e9f824f39 /bootstrap/parse.c
parenteb48600f4da4e52dd2cb46a284474c4cba8fe237 (diff)
alignof, offsetof
Diffstat (limited to 'bootstrap/parse.c')
-rw-r--r--bootstrap/parse.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/bootstrap/parse.c b/bootstrap/parse.c
index 0abaf45..31469df 100644
--- a/bootstrap/parse.c
+++ b/bootstrap/parse.c
@@ -907,8 +907,10 @@ structidx2fld(const struct type *ty, int idx) {
}
static int
-structfldnam2idx(const struct type *ty, const char *name) {
+aggfldnam2idx(const struct type *ty, const char *name) {
assert(name);
+ if (ty->t != TYunion && ty->t != TYstruct && ty->t != TYeunion)
+ return -1;
for (int i = 0; i < ty->agg.flds.n; ++i)
if (!strcmp(name, ty->agg.flds.d[i].name))
return i;
@@ -917,7 +919,7 @@ structfldnam2idx(const struct type *ty, const char *name) {
static struct aggfield *
findaggfield(const struct type *ty, const char *name) {
- int i = structfldnam2idx(ty, name);
+ int i = aggfldnam2idx(ty, name);
return i < 0 ? NULL : &ty->agg.flds.d[i];
}
@@ -957,7 +959,7 @@ parsestructini(struct parser *P, const struct type *ty) {
if (lexmatch(P, &tok, '.')) {
const char *fnam = (tok = lexexpect(P, TKident)).str;
lexexpect(P, ':');
- idx = structfldnam2idx(ty, fnam);
+ idx = aggfldnam2idx(ty, fnam);
if (idx < 0)
fatal(P, tok.span, "%s %t has no field `%s'", kind, ty, fnam);
}
@@ -1225,7 +1227,7 @@ pexprimary(struct parser *P) {
ex.span = tok.span;
} else if (lexmatch(P, &tok, TKkw_sizeof)) {
ex.t = Eintlit;
- ex.ty = ty_isize;
+ ex.ty = ty_usize;
if (lexmatch(P, &tok, '(')) {
struct expr exp = parseexpr(P);
ex.i = exp.ty->size;
@@ -1234,6 +1236,40 @@ pexprimary(struct parser *P) {
const struct type *ty = parsetype(P);
ex.i = ty->size;
}
+ } else if (lexmatch(P, &tok, TKkw_alignof)) {
+ ex.t = Eintlit;
+ ex.ty = ty_usize;
+ if (lexmatch(P, &tok, '(')) {
+ struct expr exp = parseexpr(P);
+ ex.i = exp.ty->align;
+ lexexpect(P, ')');
+ } else {
+ const struct type *ty = parsetype(P);
+ ex.i = ty->align;
+ }
+ } else if (lexmatch(P, &tok, TKkw_offsetof)) {
+ lexexpect(P, '(');
+ const struct type *ty = parsetype(P);
+ lexexpect(P, ',');
+ size_t off = 0;
+ for (;;) {
+ const char *name = (tok = lexexpect(P, TKident)).str;
+ struct aggfield *fld = findaggfield(ty, name);
+ if (!fld) {
+ fatal(P, tok.span, "%t has no such field %T", ty, tok);
+ }
+ off += fld->off;
+ ty = fld->ty;
+ if (!lexmatch(P, &tok, '.')) {
+ lexmatch(P, &tok, ',');
+ lexexpect(P, ')');
+ break;
+ }
+ }
+ ex.t = Eintlit;
+ ex.ty = ty_usize;
+ ex.u = off;
+
} else {
experr:
fatal(P, tok.span, "expected expression (near %s)", tok2str(tok));
@@ -1424,7 +1460,7 @@ pexpostfix(struct parser *P) {
bool konst = ty->konst;
ty = unconstify(ty);
if (ty->t == TYstruct || ty->t == TYunion || ty->t == TYeunion) {
- int idx = structfldnam2idx(ty, fnam);
+ int idx = aggfldnam2idx(ty, fnam);
struct aggfield *fld = &ty->agg.flds.d[idx];
if (idx < 0)
fatal(P, tok.span, "%t has no such field `%s'", ty, fnam);