aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2023-05-28 09:17:02 +0200
committerlemon <lsof@mailbox.org>2023-05-28 09:17:02 +0200
commit0be496ba1ca5695091494576fb18e4368789b491 (patch)
treefc61ddfe2f0f1d4a602175f158ca48c8037768fa
parent0f53520c5ee5f07ec2ba0361172fd72bd1456ad4 (diff)
cleanup
-rw-r--r--eval.c1
-rw-r--r--lex.c2
-rw-r--r--parse.c330
-rw-r--r--parse.h2
-rw-r--r--test.c2
5 files changed, 188 insertions, 149 deletions
diff --git a/eval.c b/eval.c
index ecfc9ed..8b4e7fb 100644
--- a/eval.c
+++ b/eval.c
@@ -195,6 +195,7 @@ binop(struct expr *ex, enum evalmode mode)
default: return 0;
#undef ef
}
+
return numcast(ex->ty.t, ex, lhs);
}
diff --git a/lex.c b/lex.c
index bad05c8..7ffe8e0 100644
--- a/lex.c
+++ b/lex.c
@@ -286,7 +286,7 @@ readstrchrlit(struct parser *pr, struct token *tk, char delim)
vpush(&b, 0);
tk->t = TKSTRLIT;
tk->s.p = alloc(&pr->exarena, b.n, 1);
- memcpy(tk->s.p, b.p, tk->s.n = b.n);
+ memcpy(tk->s.p, b.p, tk->s.n = b.n-1);
} else {
if (b.n == 0) {
span.sl = (struct span0) { idx, pr->chridx - idx, pr->fileid };
diff --git a/parse.c b/parse.c
index 0f15c39..d2ba738 100644
--- a/parse.c
+++ b/parse.c
@@ -123,7 +123,7 @@ redeclarationok(const struct decl *old, const struct decl *new)
if (old->scls != new->scls) return 0;
switch (old->scls) {
case SCTYPEDEF:
- return old->t.bits == new->t.bits;
+ return old->ty.bits == new->ty.bits;
}
return 0;
}
@@ -206,32 +206,15 @@ deftagged(struct parser *pr, struct span *span, enum typetag tt, const char *nam
return l->t = mktagtype(name, &td);
}
-/********/
-/* EXPR */
-/********/
-
-#define iszero(ex) ((ex).t == ENUMLIT && (ex).u == 0)
-
-#define mkexpr(t_,span_,ty_,...) ((struct expr){.t=(t_), .ty=(ty_), .span=(span_), __VA_ARGS__})
-
-static struct expr *
-exprdup(struct parser *pr, const struct expr *e)
-{
- return memcpy(alloc(&pr->exarena, sizeof *e, 0), e, sizeof *e);
-}
-static struct expr *
-exprdup2(struct parser *pr, const struct expr *e1, const struct expr *e2)
-{
- struct expr *r = alloc(&pr->exarena, 2*sizeof *r, 0);
- r[0] = *e1;
- r[1] = *e2;
- return r;
-}
+/*******************/
+/*** EXPRESSIONS ***/
+/*******************/
-static struct expr expr(struct parser *pr);
-static struct expr commaexpr(struct parser *pr);
+/**********************/
+/* EXPR TYPE CHECKING */
+/**********************/
-/* TODO recursive descent is probably slow, use precedence climbing? */
+#define iszero(ex) ((ex).t == ENUMLIT && (ex).u == 0)
static bool
islvalue(const struct expr *ex)
@@ -240,7 +223,7 @@ islvalue(const struct expr *ex)
return ex->t == ESYM || ex->t == EDEREF;
}
-static union type
+static union type /* 6.5.2.6 default argument promotions */
argpromote(union type t)
{
if (isint(t)) t.t = intpromote(t.t);
@@ -269,7 +252,7 @@ incdeccheck(enum toktag tt, const struct expr *ex, const struct span *span)
error(span, "arithmetic on function pointer (%ty)", ex->ty);
}
-static bool
+static bool /* 6.5.4 Cast operators */
castcheck(union type to, const struct expr *ex)
{
union type src = ex->ty;
@@ -283,7 +266,7 @@ castcheck(union type to, const struct expr *ex)
return 0;
}
-static union type
+static union type /* 6.5.2.1 Array subscripting */
subscriptcheck(const struct expr *ex, const struct expr *rhs, const struct span *span)
{
union type ty;
@@ -304,16 +287,16 @@ subscriptcheck(const struct expr *ex, const struct expr *rhs, const struct span
return ty;
}
-static bool
-isnullpo(const struct expr *ex)
+static void /* 6.5.3.4 The sizeof operator */
+sizeofcheck(const struct span *span, union type ty)
{
- static const union type voidptr = {{ TYPTR, .flag = TFCHLDPRIM, .child = TYVOID }};
- if (ex->t == ECAST && ex->ty.bits == voidptr.bits)
- ex = ex->sub;
- return iszero(*ex);
+ if (isincomplete(ty))
+ error(span, "cannot apply sizeof to incomplete type (%ty)", ty);
+ else if (ty.t == TYFUNC)
+ error(span, "cannot apply sizeof to function type (%ty)", ty);
}
-static bool
+static bool /* 6.5.8 Relational operators */
relationalcheck(const struct expr *a, const struct expr *b)
{
union type t1 = a->ty, t2 = b->ty;
@@ -327,6 +310,15 @@ relationalcheck(const struct expr *a, const struct expr *b)
}
static bool
+isnullpo(const struct expr *ex) /* match '0' or '(void *) 0' */
+{
+ static const union type voidptr = {{ TYPTR, .flag = TFCHLDPRIM, .child = TYVOID }};
+ if (ex->t == ECAST && ex->ty.bits == voidptr.bits)
+ ex = ex->sub;
+ return iszero(*ex);
+}
+
+static bool /* 6.5.9 Equality operators */
equalitycheck(const struct expr *a, const struct expr *b)
{
union type t1 = a->ty, t2 = b->ty;
@@ -340,62 +332,7 @@ equalitycheck(const struct expr *a, const struct expr *b)
return isptrcvt(t2) && isnullpo(a);
}
-static struct expr
-callexpr(struct parser *pr, const struct span *span_, const struct expr *callee)
-{
- struct token tk;
- struct expr ex, arg;
- struct span span = callee->span;
- union type ty = callee->ty;
- const struct typedata *td = &typedata[ty.dat];
- struct expr argbuf[10];
- vec_of(struct expr) args = VINIT(argbuf, arraylength(argbuf));
- bool spanok = joinspan(&span.ex, span_->ex);
- bool printsig = 0;
-
- if (ty.t == TYPTR) /* auto-deref when calling a function pointer */
- ty = typechild(ty);
- if (ty.t != TYFUNC) error(&callee->span, "calling a value of type '%ty'", callee->ty);
- if (!match(pr, &tk, ')')) for (;;) {
- arg = expr(pr);
- spanok = spanok && joinspan(&span.ex, callee->span.ex);
- if (ty.t == TYFUNC && args.n == td->nmemb && !td->variadic && !td->kandr) {
- error(&arg.span, "too many args to function taking %d params", td->nmemb);
- printsig = 1;
- }
- if (ty.t == TYFUNC && args.n < td->nmemb && !td->kandr) {
- if (!assigncheck(td->param[args.n], &arg)) {
- error(&arg.span, "arg #%d of type '%ty' is incompatible with '%ty'",
- args.n+1, arg.ty, td->param[args.n]);
- printsig = 1;
- }
- }
- vpush(&args, arg);
- peek(pr, &tk);
- if (match(pr, &tk, ',')) {
- spanok = spanok && joinspan(&span.ex, tk.span.ex);
- } else if (expect(pr, ')', "or ',' after arg")) {
- break;
- }
- }
- if (!spanok || !joinspan(&span.ex, tk.span.ex)) span = *span_;
-
- if (!td->variadic && !td->kandr && args.n < td->nmemb) {
- error(&tk.span, "not enough args to function taking %d param%s",
- td->nmemb, td->nmemb != 1 ? "s" : "");
- printsig = 1;
- }
- if (printsig) note(&callee->span, "function signature is %ty", ty);
-
- ex = mkexpr(ECALL, span, ty.t == TYFUNC ? td->ret : ty, .narg = args.n,
- .sub = alloc(&pr->exarena, (args.n+1)*sizeof(struct expr), 0));
- ex.sub[0] = *callee;
- memcpy(ex.sub+1, args.p, args.n*sizeof(struct expr));
- vfree(&args);
- return ex;
-}
-
-static union type /* 6.5.15 Conditional operator Constraints */
+static union type /* 6.5.15 Conditional operator */
condtype(const struct expr *a, const struct expr *b)
{
union type t1 = typedecay(a->ty), t2 = typedecay(b->ty), s1, s2;
@@ -419,11 +356,13 @@ bintypeerr(const struct span *span, enum toktag tt, union type lhs, union type r
error(span, "bad operands to %tt (%ty, %ty)", tt, lhs, rhs);
}
-enum binopclass{
- BCSET = 1<<7,
+enum binopclass { /* binary operator type-checking classes */
+ BCSET = 1<<7, /* is a (compound) assignment operator? */
BCSEQ = 1, BCADDITIVE, BCARITH, BCINT, BCSHFT, BCEQL, BCCMP, BCLOG,
};
+/* table indexed by binary op token;
+ * containing precedence level, expression kind and type-checking class */
static const struct { uchar prec, t, k; } bintab[] = {
['*'] = {13, EMUL, BCARITH},
['/'] = {13, EDIV, BCARITH},
@@ -443,7 +382,7 @@ static const struct { uchar prec, t, k; } bintab[] = {
['|'] = {6, EBIOR, BCINT},
[TKLOGAND] = {5, ELOGAND, BCLOG},
[TKLOGIOR] = {4, ELOGIOR, BCLOG},
- ['?'] = {3, ECOND},
+ ['?'] = {3, ECOND}, /* not actually a binop (special cased) */
['='] = {2, ESET, BCSET},
[TKSETADD] = {2, ESETADD, BCSET|BCADDITIVE}, [TKSETSUB] = {2, ESETSUB, BCSET|BCADDITIVE},
[TKSETMUL] = {2, ESETMUL, BCSET|BCARITH}, [TKSETDIV] = {2, ESETDIV, BCSET|BCARITH},
@@ -482,7 +421,7 @@ bintypecheck(const struct span *span, enum toktag tt, struct expr *lhs, struct e
break;
case BCADDITIVE:
if (tt == '+' && isptrcvt(rhs->ty)) {
- /* int + ptr -> ptr + int */
+ /* int + ptr -> ptr + int (for convenience) */
const struct expr swaptmp = *lhs;
*lhs = *rhs;
*rhs = swaptmp;
@@ -529,7 +468,7 @@ bintypecheck(const struct span *span, enum toktag tt, struct expr *lhs, struct e
ty = cvtarith(ty, rhs->ty);
assert(ty.t);
break;
- case BCSHFT:
+ case BCSHFT: /* 6.5.7 Bitwise shift operators */
if (!isint(ty) || !isint(rhs->ty))
goto Error;
ty.t = intpromote(ty.t);
@@ -545,7 +484,7 @@ bintypecheck(const struct span *span, enum toktag tt, struct expr *lhs, struct e
goto Error;
ty = mktype(TYINT);
break;
- case BCLOG:
+ case BCLOG: /* 6.5.13-14 Logical AND/OR operator */
if (!isscalar(ty) || !isscalar(rhs->ty))
goto Error;
ty = mktype(TYINT);
@@ -554,6 +493,83 @@ bintypecheck(const struct span *span, enum toktag tt, struct expr *lhs, struct e
return (k & BCSET) || !ty.t ? lhs->ty : ty;
}
+/****************/
+/* EXPR PARSING */
+/****************/
+
+#define mkexpr(t_,span_,ty_,...) ((struct expr){.t=(t_), .ty=(ty_), .span=(span_), __VA_ARGS__})
+
+static struct expr *
+exprdup(struct parser *pr, const struct expr *e)
+{
+ return memcpy(alloc(&pr->exarena, sizeof *e, 0), e, sizeof *e);
+}
+static struct expr *
+exprdup2(struct parser *pr, const struct expr *e1, const struct expr *e2)
+{
+ struct expr *r = alloc(&pr->exarena, 2*sizeof *r, 0);
+ r[0] = *e1, r[1] = *e2;
+ return r;
+}
+
+static struct expr expr(struct parser *pr);
+static struct expr commaexpr(struct parser *pr);
+
+static struct expr /* 6.5.2.2 Function calls */
+callexpr(struct parser *pr, const struct span *span_, const struct expr *callee)
+{
+ struct token tk;
+ struct expr ex, arg;
+ struct span span = callee->span;
+ union type ty = callee->ty;
+ const struct typedata *td = &typedata[ty.dat];
+ struct expr argbuf[10];
+ vec_of(struct expr) args = VINIT(argbuf, arraylength(argbuf));
+ bool spanok = joinspan(&span.ex, span_->ex);
+ bool printsig = 0;
+
+ if (ty.t == TYPTR) /* auto-deref when calling a function pointer */
+ ty = typechild(ty);
+ if (ty.t != TYFUNC) error(&callee->span, "calling a value of type '%ty'", callee->ty);
+ if (!match(pr, &tk, ')')) for (;;) {
+ arg = expr(pr);
+ spanok = spanok && joinspan(&span.ex, callee->span.ex);
+ if (ty.t == TYFUNC && args.n == td->nmemb && !td->variadic && !td->kandr) {
+ error(&arg.span, "too many args to function taking %d params", td->nmemb);
+ printsig = 1;
+ }
+ if (ty.t == TYFUNC && args.n < td->nmemb && !td->kandr) {
+ if (!assigncheck(td->param[args.n], &arg)) {
+ error(&arg.span, "arg #%d of type '%ty' is incompatible with '%ty'",
+ args.n+1, arg.ty, td->param[args.n]);
+ printsig = 1;
+ }
+ }
+ vpush(&args, arg);
+ peek(pr, &tk);
+ if (match(pr, &tk, ',')) {
+ spanok = spanok && joinspan(&span.ex, tk.span.ex);
+ } else if (expect(pr, ')', "or ',' after arg")) {
+ break;
+ }
+ }
+ if (!spanok || !joinspan(&span.ex, tk.span.ex)) span = *span_;
+
+ if (!td->variadic && !td->kandr && args.n < td->nmemb) {
+ error(&tk.span, "not enough args to function taking %d param%s",
+ td->nmemb, td->nmemb != 1 ? "s" : "");
+ printsig = 1;
+ }
+ if (printsig) note(&callee->span, "function signature is %ty", ty);
+
+ ex = mkexpr(ECALL, span, ty.t == TYFUNC ? td->ret : ty, .narg = args.n,
+ .sub = alloc(&pr->exarena, (args.n+1)*sizeof(struct expr), 0));
+ ex.sub[0] = *callee;
+ memcpy(ex.sub+1, args.p, args.n*sizeof(struct expr));
+ vfree(&args);
+ return ex;
+}
+
static inline int
tkprec(int tt)
{
@@ -587,6 +603,7 @@ Unary:
/* unary operators (gather) */
case '+': case '-': case '~': case '!':
case '*': case '&': case TKINC: case TKDEC:
+ Unops:
unops[nunop].span = tk.span;
unops[nunop].t0 = 0;
unops[nunop].tt = tk.t;
@@ -613,30 +630,47 @@ Unary:
ex = mkexpr(ESYM, tk.span, mktype(TYINT), .sym = NULL);
} else if (decl->scls == SCTYPEDEF) {
error(&tk.span, "unexpected typename %'tk (expected expression)", &tk);
- ex = mkexpr(ESYM, tk.span, decl->t, .sym = NULL);
+ ex = mkexpr(ESYM, tk.span, decl->ty, .sym = NULL);
} else {
- ex = mkexpr(ESYM, tk.span, decl->t, .qual = decl->qual, .sym = decl);
+ ex = mkexpr(ESYM, tk.span, decl->ty, .qual = decl->qual, .sym = decl);
}
break;
+ /* might be unary op or primary expr */
case '(':
- if (!isdecltok(pr)) { /* ( expr ) */
+ if (!isdecltok(pr)) { /* (expr) */
ex = commaexpr(pr);
expect(pr, ')', NULL);
break;
- } else {
+ } else { /* (type) expr */
struct declstate st = { DCASTEXPR };
struct decl decl = pdecl(&st, pr);
expect(pr, ')', NULL);
- assert(decl.t.t);
+ assert(decl.ty.t);
unops[nunop].span = tk.span;
- unops[nunop].ty = decl.t;
+ unops[nunop].ty = decl.ty;
if (++nunop >= arraylength(unops)) {
ex = exprparse(pr, 999);
break;
}
goto Unary;
}
+ case TKWsizeof:
+ span = tk.span;
+ if (!match(pr, NULL, '(')) /* sizeof expr */
+ goto Unops;
+ else if (isdecltok(pr)) { /* sizeof (type) */
+ struct declstate st = { DCASTEXPR };
+ ty = pdecl(&st, pr).ty;
+ } else { /* sizeof (expr) */
+ ty = commaexpr(pr).ty;
+ }
+ peek(pr, &tk);
+ if (expect(pr, ')', NULL))
+ joinspan(&span.ex, tk.span.ex);
+ sizeofcheck(&span, ty);
+ ex = mkexpr(ENUMLIT, span, mktype(targ_sizetype), .u = typesize(ty));
+ break;
default:
fatal(&tk.span, "expected expression (near %'tk)", &tk);
}
@@ -740,6 +774,10 @@ Postfix:
error(&span, "operand to unary & is not an lvalue");
ex = mkexpr(EADDROF, span, mkptrtype(ex.ty, ex.qual), .sub = exprdup(pr, &ex));
break;
+ case TKWsizeof:
+ sizeofcheck(&span, ex.ty);
+ ex = mkexpr(ENUMLIT, span, mktype(targ_sizetype), .u = typesize(ex.ty));
+ break;
default: assert(0);
}
} else { /* cast */
@@ -1327,7 +1365,7 @@ block(struct parser *pr, struct function *fn)
decl.scls = SCAUTO;
case SCAUTO:
case SCREGISTER:
- switch (align = typealign(decl.t)) {
+ switch (align = typealign(decl.ty)) {
case 1: op = Oalloca1; break;
case 2: op = Oalloca2; break;
case 4: op = Oalloca4; break;
@@ -1335,7 +1373,7 @@ block(struct parser *pr, struct function *fn)
case 16: op = Oalloca16; break;
default: assert(!"align");
}
- siz = typesize(decl.t);
+ siz = typesize(decl.ty);
nalloc = siz/align + ((siz&(align-1)) != 0);
EMITS {
decl.id = addinstr(fn,
@@ -1346,13 +1384,13 @@ block(struct parser *pr, struct function *fn)
put = 1;
ini = expr(pr);
pdecl(&st, pr);
- if (!assigncheck(decl.t, &ini)) {
+ if (!assigncheck(decl.ty, &ini)) {
struct span span = decl.span;
joinspan(&span.ex, ini.span.ex);
error(&span, "cannot initialize '%ty' variable with '%ty'",
- decl.t, ini.ty);
+ decl.ty, ini.ty);
}
- EMITS genstore(fn, decl.t, mkref(RTMP, decl.id), exprvalue(fn, &ini));
+ EMITS genstore(fn, decl.ty, mkref(RTMP, decl.id), exprvalue(fn, &ini));
}
break;
case SCTYPEDEF: break;
@@ -1377,10 +1415,10 @@ function(struct parser *pr, struct function *fn, const char **pnames, const stru
for (int i = 0; i < td->nmemb; ++i) {
if (pnames[i]) {
uint siz, align, nalloc;
- struct decl arg = { .t = td->param[i], .qual = tdgetqual(td->quals, i),
+ struct decl arg = { .ty = td->param[i], .qual = tdgetqual(td->quals, i),
.name = pnames[i], .scls = SCAUTO, .span = pspans[i] };
enum op op;
- switch (align = typealign(arg.t)) {
+ switch (align = typealign(arg.ty)) {
case 1: op = Oalloca1; break;
case 2: op = Oalloca2; break;
case 4: op = Oalloca4; break;
@@ -1388,12 +1426,12 @@ function(struct parser *pr, struct function *fn, const char **pnames, const stru
case 16: op = Oalloca16; break;
default: assert(!"align");
}
- siz = typesize(arg.t);
+ siz = typesize(arg.ty);
nalloc = siz/align + ((siz&(align-1)) != 0);
EMITS {
struct instr alloca = { op, KPTR, mkintcon(fn, KI4, nalloc) };
arg.id = addinstr(fn, alloca).idx;
- genstore(fn, arg.t, mkref(RTMP, arg.id), mkref(RARG, i));
+ genstore(fn, arg.ty, mkref(RTMP, arg.id), mkref(RARG, i));
}
putdecl(pr, &arg);
} else {
@@ -1436,19 +1474,19 @@ buildagg(struct parser *pr, enum typetag tt, const char *name, int id)
td.flexi = 0;
error(&flexspan, "flexible array member is not at end of struct");
}
- if (!isunion && decl.t.t == TYARRAY && !typearrlen(decl.t)) {
+ if (!isunion && decl.ty.t == TYARRAY && !typearrlen(decl.ty)) {
td.flexi = 1;
flexspan = decl.span;
- } else if (isincomplete(decl.t)) {
- error(&decl.span, "field has incomplete type (%ty)", decl.t);
- } else if (decl.t.t == TYFUNC) {
- error(&decl.span, "field has function type (%ty)", decl.t);
+ } else if (isincomplete(decl.ty)) {
+ error(&decl.span, "field has incomplete type (%ty)", decl.ty);
+ } else if (decl.ty.t == TYFUNC) {
+ error(&decl.span, "field has function type (%ty)", decl.ty);
}
- if (decl.t.t) {
- uint align = typealign(decl.t);
- uint siz = typesize(decl.t);
+ if (decl.ty.t) {
+ uint align = typealign(decl.ty);
+ uint siz = typesize(decl.ty);
uint off = isunion ? 0 : alignup(td.siz, align);
- struct field f = { decl.name, decl.t, off };
+ struct field f = { decl.name, decl.ty, off };
vpush(&fld, f);
if (decl.qual) {
td.anyconst |= decl.qual & QCONST;
@@ -1625,7 +1663,7 @@ declspec(struct declstate *st, struct parser *pr)
case TKIDENT:
if (!st->base.t && !arith && (decl = finddecl(pr, tk.ident))
&& decl->scls == SCTYPEDEF) {
- st->base = decl->t;
+ st->base = decl->ty;
break;
}
/* fallthru */
@@ -1854,8 +1892,8 @@ decltypes(struct parser *pr, struct decllist *list, const char **name, struct sp
break;
}
decl = pdecl(&st, pr);
- decl.t = typedecay(decl.t);
- vpush(&params, decl.t);
+ decl.ty = typedecay(decl.ty);
+ vpush(&params, decl.ty);
vpush(&names, decl.name);
vpush(&spans, decl.span);
if (decl.qual) {
@@ -1863,11 +1901,11 @@ decltypes(struct parser *pr, struct decllist *list, const char **name, struct sp
while (qual.n < tdqualsiz(params.n)) vpush(&qual, 0);
tdsetqual(qual.p, params.n-1, decl.qual);
}
- if (isincomplete(decl.t)) {
- if (params.n > 1 || decl.t.t != TYVOID || decl.qual || decl.name) {
+ if (isincomplete(decl.ty)) {
+ if (params.n > 1 || decl.ty.t != TYVOID || decl.qual || decl.name) {
error(&decl.span,
"function parameter #%d has incomplete type (%tq)",
- params.n, decl.t, tdgetqual(qual.p, params.n-1));
+ params.n, decl.ty, tdgetqual(qual.p, params.n-1));
}
}
joinspan(&node.span.ex, tk.span.ex);
@@ -1918,25 +1956,25 @@ declarator(struct declstate *st, struct parser *pr) {
for (l = list.prev; l != &list; l = l->prev) {
switch (l->t) {
case TYPTR:
- decl.t = mkptrtype(decl.t, decl.qual);
+ decl.ty = mkptrtype(decl.ty, decl.qual);
decl.qual = l->qual;
break;
case TYARRAY:
- if (isincomplete(decl.t))
- error(&l->span, "array has incomplete element type (%ty)", decl.t);
- else if (decl.t.t == TYFUNC)
- error(&l->span, "array has element has function type (%ty)", decl.t);
- decl.t = mkarrtype(decl.t, decl.qual, l->len);
+ if (isincomplete(decl.ty))
+ error(&l->span, "array has incomplete element type (%ty)", decl.ty);
+ else if (decl.ty.t == TYFUNC)
+ error(&l->span, "array has element has function type (%ty)", decl.ty);
+ decl.ty = mkarrtype(decl.ty, decl.qual, l->len);
decl.qual = 0;
break;
case TYFUNC:
- if (decl.t.t == TYFUNC)
- error(&decl.span, "function cannot return function type (%ty)", decl.t);
- else if (decl.t.t == TYARRAY)
- error(&decl.span, "function cannot return array type", decl.t);
- else if (decl.t.t != TYVOID && isincomplete(decl.t))
- error(&decl.span, "function cannot return incomplete type (%ty)", decl.t);
- decl.t = mkfntype(decl.t, l->npar, l->param, l->pqual, l->kandr, l->variadic);
+ if (decl.ty.t == TYFUNC)
+ error(&decl.span, "function cannot return function type (%ty)", decl.ty);
+ else if (decl.ty.t == TYARRAY)
+ error(&decl.span, "function cannot return array type", decl.ty);
+ else if (decl.ty.t != TYVOID && isincomplete(decl.ty))
+ error(&decl.span, "function cannot return incomplete type (%ty)", decl.ty);
+ decl.ty = mkfntype(decl.ty, l->npar, l->param, l->pqual, l->kandr, l->variadic);
if (l->param != declparamtmp) free(l->param);
if (l->pqual != declpqualtmp) free(l->pqual);
if (l->prev == &list && l->npar) { /* last */
@@ -2003,7 +2041,7 @@ pdecl(struct declstate *st, struct parser *pr) {
if (iniallowed && match(pr, &tk, '=')) {
st->varini = 1;
return decl;
- } else if (first && decl.t.t == TYFUNC && match(pr, &tk, '{')) {
+ } else if (first && decl.ty.t == TYFUNC && match(pr, &tk, '{')) {
st->funcdef = 1;
return decl;
}
@@ -2054,11 +2092,11 @@ parse(struct parser *pr)
}
continue;
}
- if (decl.name) efmt("%s : %tq\n", decl.name, decl.t, decl.qual);
+ if (decl.name) efmt("%s : %tq\n", decl.name, decl.ty, decl.qual);
if (st.funcdef) {
- const struct typedata *td = &typedata[decl.t.dat];
+ const struct typedata *td = &typedata[decl.ty.dat];
struct function fn = { pr->fnarena, decl.name, .globl = decl.scls != SCSTATIC };
- fn.fnty = decl.t;
+ fn.fnty = decl.ty;
fn.retty = td->ret;
putdecl(pr, &decl);
irinit(&fn);
@@ -2069,8 +2107,8 @@ parse(struct parser *pr)
if (st.varini) {
ini = expr(pr);
pdecl(&st, pr);
- if (!assigncheck(decl.t, &ini))
- error(&ini.span, "cannot initialize %ty with %ty", decl.t, ini.ty);
+ if (!assigncheck(decl.ty, &ini))
+ error(&ini.span, "cannot initialize %ty with %ty", decl.ty, ini.ty);
if (!eval(&ini, EVSTATICINI))
error(&ini.span, "cannot evaluate expression statically");
}
diff --git a/parse.h b/parse.h
index fd1cd20..d6da83f 100644
--- a/parse.h
+++ b/parse.h
@@ -168,7 +168,7 @@ enum storageclass {
};
struct decl {
- union type t;
+ union type ty;
uchar scls;
uchar qual;
ushort align;
diff --git a/test.c b/test.c
index deaa6d9..2f2a39a 100644
--- a/test.c
+++ b/test.c
@@ -20,7 +20,7 @@ int abs(int x){
int popcnt(unsigned x) {
int n = 0;
while (x) x >>= 1, n++;
- return n;
+ return n + sizeof &"รก"[0];
}
struct f {