diff options
Diffstat (limited to 'expr.c')
-rw-r--r-- | expr.c | 32 |
1 files changed, 22 insertions, 10 deletions
@@ -22,6 +22,7 @@ mkexpr(enum exprkind k, struct type *t, struct expr *b) e->kind = k; e->base = b; e->next = NULL; + e->toeval = NULL; return e; } @@ -602,13 +603,15 @@ generic(struct scope *s) def = assignexpr(s); } else { qual = QUALNONE; - t = typename(s, &qual); + t = typename(s, &qual, NULL); if (!t) error(&tok.loc, "expected typename for generic association"); if (t->kind == TYPEFUNC) error(&tok.loc, "generic association must have object type"); if (t->incomplete) error(&tok.loc, "generic association must have complete type"); + if (t->prop & PROPVM) + error(&tok.loc, "generic association has variably modified type"); expect(TCOLON, "after type name"); e = assignexpr(s); if (typecompatible(t, want) && qual == QUALNONE) { @@ -780,7 +783,7 @@ designator(struct scope *s, struct type *t, unsigned long long *offset) static struct expr * builtinfunc(struct scope *s, enum builtinkind kind) { - struct expr *e; + struct expr *e, *toeval; struct type *t; struct member *m; char *name; @@ -816,7 +819,7 @@ builtinfunc(struct scope *s, enum builtinkind kind) e->u.constant.f = strtod("nan", NULL); break; case BUILTINOFFSETOF: - t = typename(s, NULL); + t = typename(s, NULL, NULL); expect(TCOMMA, "after type name"); name = expect(TIDENT, "after ','"); if (t->kind != TYPESTRUCT && t->kind != TYPEUNION) @@ -830,9 +833,9 @@ builtinfunc(struct scope *s, enum builtinkind kind) free(name); break; case BUILTINTYPESCOMPATIBLEP: - t = typename(s, NULL); + t = typename(s, NULL, NULL); expect(TCOMMA, "after type name"); - e = mkconstexpr(&typeint, typecompatible(t, typename(s, NULL))); + e = mkconstexpr(&typeint, typecompatible(t, typename(s, NULL, NULL))); break; case BUILTINUNREACHABLE: e = mkexpr(EXPRBUILTIN, &typevoid, NULL); @@ -846,7 +849,8 @@ builtinfunc(struct scope *s, enum builtinkind kind) if (typeadjvalist == targ->typevalist) e->base = mkunaryexpr(TBAND, e->base); expect(TCOMMA, "after va_list"); - e->type = typename(s, &e->qual); + e->type = typename(s, &e->qual, &toeval); + e->toeval = toeval; break; case BUILTINVACOPY: e = mkexpr(EXPRASSIGN, &typevoid, NULL); @@ -1071,12 +1075,13 @@ unaryexpr(struct scope *s) case TALIGNOF: next(); if (consume(TLPAREN)) { - t = typename(s, NULL); + t = typename(s, NULL, NULL); if (t) { expect(TRPAREN, "after type name"); /* might be part of a compound literal */ if (op == TSIZEOF && tok.kind == TLBRACE) parseinit(s, t); + e = NULL; } else { e = expr(s); expect(TRPAREN, "after expression"); @@ -1101,7 +1106,12 @@ unaryexpr(struct scope *s) error(&tok.loc, "%s operator applied to incomplete type", tokstr[op]); if (t->kind == TYPEFUNC) error(&tok.loc, "%s operator applied to function type", tokstr[op]); - e = mkconstexpr(&typeulong, op == TSIZEOF ? t->size : t->align); + if (t->kind == TYPEARRAY && t->size == 0 && op == TSIZEOF) { + e = mkexpr(EXPRSIZEOF, &typeulong, e); + e->u.szof.type = e ? t : e->base->type; + } else { + e = mkconstexpr(&typeulong, op == TSIZEOF ? t->size : t->align); + } break; default: e = postfixexpr(s, NULL); @@ -1116,13 +1126,13 @@ castexpr(struct scope *s) struct type *t, *ct; struct decl *d; enum typequal tq; - struct expr *r, *e, **end; + struct expr *r, *e, **end, *toeval; ct = NULL; end = &r; while (consume(TLPAREN)) { tq = QUALNONE; - t = typename(s, &tq); + t = typename(s, &tq, &toeval); if (!t) { e = expr(s); expect(TRPAREN, "after expression to match '('"); @@ -1132,6 +1142,7 @@ castexpr(struct scope *s) expect(TRPAREN, "after type name"); if (tok.kind == TLBRACE) { e = mkexpr(EXPRCOMPOUND, t, NULL); + e->toeval = toeval; e->qual = tq; e->lvalue = true; d = mkdecl(NULL, DECLOBJECT, t, tq, LINKNONE); @@ -1144,6 +1155,7 @@ castexpr(struct scope *s) if (t != &typevoid && !(t->prop & PROPSCALAR)) error(&tok.loc, "cast type must be scalar"); e = mkexpr(EXPRCAST, t, NULL); + e->toeval = toeval; *end = e; end = &e->base; ct = t; |