aboutsummaryrefslogtreecommitdiff
path: root/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'expr.c')
-rw-r--r--expr.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/expr.c b/expr.c
index 7e7e649..aef6fe9 100644
--- a/expr.c
+++ b/expr.c
@@ -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;