Merge func_decl_list into decl0

Removes some code duplication and also implements one feature:
checking for duplicate decls for old style parameters.
master
Michael Matz 2017-03-11 02:13:59 +01:00
parent 7aef0522b0
commit 25522e4799
1 changed files with 38 additions and 67 deletions

105
tccgen.c
View File

@ -79,7 +79,7 @@ static void parse_expr_type(CType *type);
static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only);
static void block(int *bsym, int *csym, int is_expr);
static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope);
static int decl0(int l, int is_for_loop_init);
static int decl0(int l, int is_for_loop_init, Sym *);
static void expr_eq(void);
static void vla_runtime_type_size(CType *type, int *a);
static void vla_sp_restore(void);
@ -3617,7 +3617,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
get_tok_str(v, NULL));
}
if ((type1.t & VT_BTYPE) == VT_FUNC ||
(type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
(type1.t & VT_STORAGE))
tcc_error("invalid type for '%s'",
get_tok_str(v, NULL));
}
@ -4012,7 +4012,7 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td)
n = tok;
if (n < TOK_UIDENT)
expect("identifier");
pt.t = VT_INT;
pt.t = VT_VOID; /* invalid type */
next();
}
convert_parameter_type(&pt);
@ -5697,7 +5697,7 @@ static void block(int *bsym, int *csym, int is_expr)
++local_scope;
if (tok != ';') {
/* c99 for-loop init decl? */
if (!decl0(VT_LOCAL, 1)) {
if (!decl0(VT_LOCAL, 1, NULL)) {
/* no, regular for-loop init expr */
gexpr();
vpop();
@ -6718,55 +6718,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
}
}
/* parse an old style function declaration list */
/* XXX: check multiple parameter */
static void func_decl_list(Sym *func_sym)
{
AttributeDef ad;
int v;
Sym *s;
CType btype, type;
/* parse each declaration */
while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF &&
tok != TOK_ASM1 && tok != TOK_ASM2 && tok != TOK_ASM3) {
if (!parse_btype(&btype, &ad))
expect("declaration list");
if (((btype.t & VT_BTYPE) == VT_ENUM ||
(btype.t & VT_BTYPE) == VT_STRUCT) &&
tok == ';') {
/* we accept no variable after */
} else {
for(;;) {
type = btype;
type_decl(&type, &ad, &v, TYPE_DIRECT);
/* find parameter in function parameter list */
s = func_sym->next;
while (s != NULL) {
if ((s->v & ~SYM_FIELD) == v)
goto found;
s = s->next;
}
tcc_error("declaration for parameter '%s' but no such parameter",
get_tok_str(v, NULL));
found:
/* check that no storage specifier except 'register' was given */
if (type.t & VT_STORAGE)
tcc_error("storage class specified for '%s'", get_tok_str(v, NULL));
convert_parameter_type(&type);
/* we can add the type (NOTE: it could be local to the function) */
s->type = type;
/* accept other parameters */
if (tok == ',')
next();
else
break;
}
}
skip(';');
}
}
/* parse a function defined by symbol 'sym' and generate its code in
'cur_text_section' */
static void gen_function(Sym *sym)
@ -6860,8 +6811,9 @@ ST_FUNC void free_inline_functions(TCCState *s)
dynarray_reset(&s->inline_fns, &s->nb_inline_fns);
}
/* 'l' is VT_LOCAL or VT_CONST to define default storage type */
static int decl0(int l, int is_for_loop_init)
/* 'l' is VT_LOCAL or VT_CONST to define default storage type, or VT_CMP
if parsing old style parameter decl list (and FUNC_SYM is set then) */
static int decl0(int l, int is_for_loop_init, Sym *func_sym)
{
int v, has_init, r;
CType type, btype;
@ -6872,9 +6824,8 @@ static int decl0(int l, int is_for_loop_init)
if (!parse_btype(&btype, &ad)) {
if (is_for_loop_init)
return 0;
/* skip redundant ';' */
/* XXX: find more elegant solution */
if (tok == ';') {
/* skip redundant ';' if not in old parameter decl scope */
if (tok == ';' && l != VT_CMP) {
next();
continue;
}
@ -6886,7 +6837,7 @@ static int decl0(int l, int is_for_loop_init)
}
/* special test for old K&R protos without explicit int
type. Only accepted when defining global data */
if (l == VT_LOCAL || tok < TOK_UIDENT)
if (l != VT_CONST || tok < TOK_UIDENT)
break;
btype.t = VT_INT;
}
@ -6926,8 +6877,8 @@ static int decl0(int l, int is_for_loop_init)
/* if old style function prototype, we accept a
declaration list */
sym = type.ref;
if (sym->c == FUNC_OLD)
func_decl_list(sym);
if (sym->c == FUNC_OLD && l == VT_CONST)
decl0(VT_CMP, 0, sym);
}
if (gnu_ext && (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
@ -6953,16 +6904,20 @@ static int decl0(int l, int is_for_loop_init)
type.t |= ad.a.visibility << VT_VIS_SHIFT;
if (tok == '{') {
if (l == VT_LOCAL)
if (l != VT_CONST)
tcc_error("cannot use local functions");
if ((type.t & VT_BTYPE) != VT_FUNC)
expect("function definition");
/* reject abstract declarators in function definition */
/* reject abstract declarators in function definition
make old style params without decl have int type */
sym = type.ref;
while ((sym = sym->next) != NULL)
while ((sym = sym->next) != NULL) {
if (!(sym->v & ~SYM_FIELD))
expect("identifier");
expect("identifier");
if (sym->type.t == VT_VOID)
sym->type = int_type;
}
/* XXX: cannot do better now: convert extern line to static inline */
if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
@ -7036,7 +6991,23 @@ static int decl0(int l, int is_for_loop_init)
}
break;
} else {
if (type.t & VT_TYPEDEF) {
if (l == VT_CMP) {
/* find parameter in function parameter list */
for (sym = func_sym->next; sym; sym = sym->next)
if ((sym->v & ~SYM_FIELD) == v)
goto found;
tcc_error("declaration for parameter '%s' but no such parameter",
get_tok_str(v, NULL));
found:
if (type.t & VT_STORAGE) /* 'register' is okay */
tcc_error("storage class specified for '%s'",
get_tok_str(v, NULL));
if (sym->type.t != VT_VOID)
tcc_error("redefinition of parameter '%s'",
get_tok_str(v, NULL));
convert_parameter_type(&type);
sym->type = type;
} else if (type.t & VT_TYPEDEF) {
/* save typedefed type */
/* XXX: test storage specifiers ? */
sym = sym_find(v);
@ -7110,7 +7081,7 @@ static int decl0(int l, int is_for_loop_init)
ST_FUNC void decl(int l)
{
decl0(l, 0);
decl0(l, 0, NULL);
}
/* ------------------------------------------------------------------------- */