diff options
| -rw-r--r-- | cc.h | 2 | ||||
| -rw-r--r-- | decl.c | 19 | ||||
| -rw-r--r-- | expr.c | 24 | ||||
| -rw-r--r-- | targ.c | 1 | ||||
| -rw-r--r-- | type.c | 18 | 
5 files changed, 36 insertions, 28 deletions
| @@ -415,6 +415,7 @@ struct type *typecomposite(struct type *, struct type *);  struct type *typeunqual(struct type *, enum typequal *);  struct type *typecommonreal(struct type *, unsigned, struct type *, unsigned);  struct type *typepromote(struct type *, unsigned); +struct type *typeadjust(struct type *);  enum typeprop typeprop(struct type *);  struct member *typemember(struct type *, const char *, uint64_t *); @@ -428,6 +429,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 *typeadjvalist;  /* targ */ @@ -618,21 +618,6 @@ declarator(struct scope *s, struct qualtype base, char **name, bool allowabstrac  	return base;  } -static struct type * -adjust(struct type *t) -{ -	switch (t->kind) { -	case TYPEARRAY: -		t = mkpointertype(t->base, t->qual); -		break; -	case TYPEFUNC: -		t = mkpointertype(t, QUALNONE); -		break; -	} - -	return t; -} -  static struct param *  parameter(struct scope *s)  { @@ -647,7 +632,7 @@ parameter(struct scope *s)  		error(&tok.loc, "parameter declaration has invalid storage-class specifier");  	t = declarator(s, t, &name, true); -	return mkparam(name, adjust(t.type), t.qual); +	return mkparam(name, typeadjust(t.type), t.qual);  }  static bool @@ -669,7 +654,7 @@ paramdecl(struct scope *s, struct param *params)  			;  		if (!p)  			error(&tok.loc, "old-style function declarator has no parameter named '%s'", name); -		p->type = adjust(t.type); +		p->type = typeadjust(t.type);  		p->qual = t.qual;  		if (tok.kind == TSEMICOLON)  			break; @@ -642,31 +642,31 @@ builtinfunc(struct scope *s, enum builtinkind kind)  	case BUILTINVAARG:  		e = mkexpr(EXPRBUILTIN, NULL);  		e->builtin.kind = BUILTINVAARG; -		e->base = mkunaryexpr(TBAND, assignexpr(s)); -		if (e->base->base->type != targ->typevalist) +		e->base = assignexpr(s); +		if (!typesame(e->base->type, typeadjvalist))  			error(&tok.loc, "va_arg argument must have type va_list"); +		if (!e->base->decayed) +			e->base = mkunaryexpr(TBAND, e->base);  		expect(TCOMMA, "after va_list");  		e->type = typename(s, &e->qual);  		break;  	case BUILTINVACOPY:  		e = mkexpr(EXPRASSIGN, &typevoid);  		e->assign.l = assignexpr(s); +		if (!typesame(e->assign.l->type, typeadjvalist)) +			error(&tok.loc, "va_copy destination must have type va_list");  		if (e->assign.l->decayed)  			e->assign.l = e->assign.l->base; -		if (e->assign.l->type != targ->typevalist) -			error(&tok.loc, "va_copy destination must have type va_list");  		expect(TCOMMA, "after target va_list");  		e->assign.r = assignexpr(s); +		if (!typesame(e->assign.r->type, typeadjvalist)) +			error(&tok.loc, "va_copy source must have type va_list");  		if (e->assign.r->decayed)  			e->assign.r = e->assign.r->base; -		if (e->assign.r->type != targ->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 != targ->typevalist) +		if (!typesame(e->type, typeadjvalist))  			error(&tok.loc, "va_end argument must have type va_list");  		e = mkexpr(EXPRBUILTIN, &typevoid);  		e->builtin.kind = BUILTINVAEND; @@ -674,9 +674,11 @@ builtinfunc(struct scope *s, enum builtinkind kind)  	case BUILTINVASTART:  		e = mkexpr(EXPRBUILTIN, &typevoid);  		e->builtin.kind = BUILTINVASTART; -		e->base = mkunaryexpr(TBAND, assignexpr(s)); -		if (e->base->base->type != targ->typevalist) +		e->base = assignexpr(s); +		if (!typesame(e->base->type, typeadjvalist))  			error(&tok.loc, "va_start argument must have type va_list"); +		if (!e->base->decayed) +			e->base = mkunaryexpr(TBAND, e->base);  		expect(TCOMMA, "after va_list");  		param = assignexpr(s);  		if (param->kind != EXPRIDENT) @@ -55,4 +55,5 @@ targinit(const char *name)  	if (!targ)  		fatal("unknown target '%s'", name);  	typechar.basic.issigned = targ->signedchar; +	typeadjvalist = typeadjust(targ->typevalist);  } @@ -39,6 +39,8 @@ struct type typefloat   = FLTTYPE(TYPEFLOAT, 4);  struct type typedouble  = FLTTYPE(TYPEDOUBLE, 8);  struct type typeldouble = FLTTYPE(TYPELDOUBLE, 16); +struct type *typeadjvalist; +  struct type *  mktype(enum typekind kind, enum typeprop prop)  { @@ -216,6 +218,22 @@ typecommonreal(struct type *t1, unsigned w1, struct type *t2, unsigned w2)  	fatal("internal error; could not find common real type");  } +/* function parameter type adjustment (C11 6.7.6.3p7) */ +struct type * +typeadjust(struct type *t) +{ +	switch (t->kind) { +	case TYPEARRAY: +		t = mkpointertype(t->base, t->qual); +		break; +	case TYPEFUNC: +		t = mkpointertype(t, QUALNONE); +		break; +	} + +	return t; +} +  struct member *  typemember(struct type *t, const char *name, uint64_t *offset)  { | 
