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