diff options
| author | 2022-08-19 06:50:12 +0200 | |
|---|---|---|
| committer | 2022-08-19 06:50:12 +0200 | |
| commit | 01969818aec859611ca1989783b6e0d7f81bdf9e (patch) | |
| tree | 80324a21b5b4647107d6596eaabd741e9f824f39 /bootstrap/parse.c | |
| parent | eb48600f4da4e52dd2cb46a284474c4cba8fe237 (diff) | |
alignof, offsetof
Diffstat (limited to 'bootstrap/parse.c')
| -rw-r--r-- | bootstrap/parse.c | 46 |
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); |