aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cc.h2
-rw-r--r--expr.c29
-rw-r--r--type.c14
3 files changed, 28 insertions, 17 deletions
diff --git a/cc.h b/cc.h
index 3b33e8c..9c4484b 100644
--- a/cc.h
+++ b/cc.h
@@ -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 */
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)
diff --git a/type.c b/type.c
index f58247a..a97175a 100644
--- a/type.c
+++ b/type.c
@@ -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 *