diff options
-rw-r--r-- | cc.h | 2 | ||||
-rw-r--r-- | expr.c | 29 | ||||
-rw-r--r-- | type.c | 14 |
3 files changed, 28 insertions, 17 deletions
@@ -428,7 +428,7 @@ extern struct type typeint, typeuint; extern struct type typelong, typeulong; extern struct type typellong, typeullong; extern struct type typefloat, typedouble, typeldouble; -extern struct type typevalist, typevalistptr; +extern struct type typevalist; /* targ */ @@ -642,26 +642,41 @@ builtinfunc(struct scope *s, enum builtinkind kind) case BUILTINVAARG: e = mkexpr(EXPRBUILTIN, NULL); e->builtin.kind = BUILTINVAARG; - e->base = exprconvert(assignexpr(s), &typevalistptr); + e->base = mkunaryexpr(TBAND, assignexpr(s)); + if (e->base->base->type != &typevalist) + error(&tok.loc, "va_arg argument must have type va_list"); expect(TCOMMA, "after va_list"); e->type = typename(s, &e->qual); break; case BUILTINVACOPY: - e = mkexpr(EXPRASSIGN, typevalist.base); - e->assign.l = mkunaryexpr(TMUL, exprconvert(assignexpr(s), &typevalistptr)); + e = mkexpr(EXPRASSIGN, &typevoid); + e->assign.l = assignexpr(s); + if (e->assign.l->decayed) + e->assign.l = e->assign.l->base; + if (e->assign.l->type != &typevalist) + error(&tok.loc, "va_copy destination must have type va_list"); expect(TCOMMA, "after target va_list"); - e->assign.r = mkunaryexpr(TMUL, exprconvert(assignexpr(s), &typevalistptr)); - e = exprconvert(e, &typevoid); + e->assign.r = assignexpr(s); + if (e->assign.r->decayed) + e->assign.r = e->assign.r->base; + if (e->assign.r->type != &typevalist) + error(&tok.loc, "va_copy source must have type va_list"); break; case BUILTINVAEND: + e = assignexpr(s); + if (e->decayed) + e = e->base; + if (e->type != &typevalist) + error(&tok.loc, "va_end argument must have type va_list"); e = mkexpr(EXPRBUILTIN, &typevoid); e->builtin.kind = BUILTINVAEND; - exprconvert(assignexpr(s), &typevalistptr); break; case BUILTINVASTART: e = mkexpr(EXPRBUILTIN, &typevoid); e->builtin.kind = BUILTINVASTART; - e->base = exprconvert(assignexpr(s), &typevalistptr); + e->base = mkunaryexpr(TBAND, assignexpr(s)); + if (e->base->base->type != &typevalist) + error(&tok.loc, "va_start argument must have type va_list"); expect(TCOMMA, "after va_list"); param = assignexpr(s); if (param->kind != EXPRIDENT) @@ -39,17 +39,13 @@ struct type typefloat = FLTTYPE(TYPEFLOAT, 4); struct type typedouble = FLTTYPE(TYPEDOUBLE, 8); struct type typeldouble = FLTTYPE(TYPELDOUBLE, 16); -static struct type typevaliststruct = { - .kind = TYPESTRUCT, .size = 32, .align = 8, - .prop = PROPOBJECT|PROPAGGR, -}; struct type typevalist = { - .kind = TYPEARRAY, .size = 32, .align = 8, .array = {1}, .base = &typevaliststruct, + .kind = TYPEARRAY, .size = 32, .align = 8, .array = {1}, .prop = PROPOBJECT|PROPDERIVED|PROPAGGR, -}; -struct type typevalistptr = { - .kind = TYPEPOINTER, .size = 8, .align = 8, .base = &typevaliststruct, - .prop = PROPOBJECT|PROPDERIVED|PROPSCALAR, + .base = &(struct type){ + .kind = TYPESTRUCT, .size = 32, .align = 8, + .prop = PROPOBJECT|PROPAGGR, + }, }; struct type * |