forked from Mirrors/tinycc
Reorganize type parsing
Various corner cases for declarator parsing were incorrect. This reorganizes and fixes it, and somewhat simplifies it as well.master
parent
5891fbc0c8
commit
182367e232
121
tccgen.c
121
tccgen.c
|
@ -74,7 +74,7 @@ static void gen_cast(CType *type);
|
|||
static inline CType *pointed_type(CType *type);
|
||||
static int is_compatible_types(CType *type1, CType *type2);
|
||||
static int parse_btype(CType *type, AttributeDef *ad);
|
||||
static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
|
||||
static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);
|
||||
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);
|
||||
|
@ -3586,7 +3586,8 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
|
|||
v = 0;
|
||||
type1 = btype;
|
||||
if (tok != ':') {
|
||||
type_decl(&type1, &ad1, &v, TYPE_DIRECT | TYPE_ABSTRACT);
|
||||
if (tok != ';')
|
||||
type_decl(&type1, &ad1, &v, TYPE_DIRECT);
|
||||
if (v == 0) {
|
||||
if ((type1.t & VT_BTYPE) != VT_STRUCT)
|
||||
expect("identifier");
|
||||
|
@ -3964,7 +3965,7 @@ static int asm_label_instr(void)
|
|||
return v;
|
||||
}
|
||||
|
||||
static void post_type(CType *type, AttributeDef *ad, int storage)
|
||||
static int post_type(CType *type, AttributeDef *ad, int storage, int td)
|
||||
{
|
||||
int n, l, t1, arg_size, align;
|
||||
Sym **plast, *s, *first;
|
||||
|
@ -3972,25 +3973,25 @@ static void post_type(CType *type, AttributeDef *ad, int storage)
|
|||
CType pt;
|
||||
|
||||
if (tok == '(') {
|
||||
/* function declaration */
|
||||
/* function type, or recursive declarator (return if so) */
|
||||
next();
|
||||
l = 0;
|
||||
if (td && !(td & TYPE_ABSTRACT))
|
||||
return 0;
|
||||
if (tok == ')')
|
||||
l = 0;
|
||||
else if (parse_btype(&pt, &ad1))
|
||||
l = FUNC_NEW;
|
||||
else if (td)
|
||||
return 0;
|
||||
else
|
||||
l = FUNC_OLD;
|
||||
first = NULL;
|
||||
plast = &first;
|
||||
arg_size = 0;
|
||||
if (tok != ')') {
|
||||
if (l) {
|
||||
for(;;) {
|
||||
/* read param name and compute offset */
|
||||
if (l != FUNC_OLD) {
|
||||
if (!parse_btype(&pt, &ad1)) {
|
||||
if (l) {
|
||||
tcc_error("invalid type");
|
||||
} else {
|
||||
l = FUNC_OLD;
|
||||
goto old_proto;
|
||||
}
|
||||
}
|
||||
l = FUNC_NEW;
|
||||
if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
|
||||
break;
|
||||
type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
|
||||
|
@ -3998,7 +3999,6 @@ static void post_type(CType *type, AttributeDef *ad, int storage)
|
|||
tcc_error("parameter declared as void");
|
||||
arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE;
|
||||
} else {
|
||||
old_proto:
|
||||
n = tok;
|
||||
if (n < TOK_UIDENT)
|
||||
expect("identifier");
|
||||
|
@ -4017,10 +4017,11 @@ static void post_type(CType *type, AttributeDef *ad, int storage)
|
|||
next();
|
||||
break;
|
||||
}
|
||||
if (l == FUNC_NEW && !parse_btype(&pt, &ad1))
|
||||
tcc_error("invalid type");
|
||||
}
|
||||
}
|
||||
/* if no parameters, then old type prototype */
|
||||
if (l == 0)
|
||||
} else
|
||||
/* if no parameters, then old type prototype */
|
||||
l = FUNC_OLD;
|
||||
skip(')');
|
||||
/* NOTE: const is ignored in returned type as it has a special
|
||||
|
@ -4072,7 +4073,7 @@ static void post_type(CType *type, AttributeDef *ad, int storage)
|
|||
}
|
||||
skip(']');
|
||||
/* parse next post type */
|
||||
post_type(type, ad, storage);
|
||||
post_type(type, ad, storage, 0);
|
||||
if (type->t == VT_FUNC)
|
||||
tcc_error("declaration of an array of functions");
|
||||
t1 |= type->t & VT_VLA;
|
||||
|
@ -4098,20 +4099,25 @@ static void post_type(CType *type, AttributeDef *ad, int storage)
|
|||
type->t = (t1 ? VT_VLA : VT_ARRAY) | VT_PTR;
|
||||
type->ref = s;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Parse a type declaration (except basic type), and return the type
|
||||
/* Parse a type declarator (except basic type), and return the type
|
||||
in 'type'. 'td' is a bitmask indicating which kind of type decl is
|
||||
expected. 'type' should contain the basic type. 'ad' is the
|
||||
attribute definition of the basic type. It can be modified by
|
||||
type_decl().
|
||||
*/
|
||||
static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
|
||||
type_decl(). If this (possibly abstract) declarator is a pointer chain
|
||||
it returns the innermost pointed to type (equals *type, but is a different
|
||||
pointer), otherwise returns type itself, that's used for recursive calls. */
|
||||
static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td)
|
||||
{
|
||||
Sym *s;
|
||||
CType type1, *type2;
|
||||
CType *post, *ret;
|
||||
int qualifiers, storage;
|
||||
|
||||
/* recursive type, remove storage bits first, apply them later again */
|
||||
storage = type->t & VT_STORAGE;
|
||||
type->t &= ~VT_STORAGE;
|
||||
post = ret = type;
|
||||
while (tok == '*') {
|
||||
qualifiers = 0;
|
||||
redo:
|
||||
|
@ -4139,51 +4145,38 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
|
|||
}
|
||||
mk_pointer(type);
|
||||
type->t |= qualifiers;
|
||||
if (ret == type)
|
||||
/* innermost pointed to type is the one for the first derivation */
|
||||
ret = pointed_type(type);
|
||||
}
|
||||
|
||||
/* recursive type */
|
||||
/* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
|
||||
type1.t = 0; /* XXX: same as int */
|
||||
if (tok == '(') {
|
||||
next();
|
||||
/* XXX: this is not correct to modify 'ad' at this point, but
|
||||
the syntax is not clear */
|
||||
if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
|
||||
parse_attribute(ad);
|
||||
type_decl(&type1, ad, v, td);
|
||||
skip(')');
|
||||
/* This is possibly a parameter type list for abstract declarators
|
||||
('int ()'), use post_type for testing this. */
|
||||
if (!post_type(type, ad, 0, td)) {
|
||||
/* It's not, so it's a nested declarator, and the post operations
|
||||
apply to the innermost pointed to type (if any). */
|
||||
/* XXX: this is not correct to modify 'ad' at this point, but
|
||||
the syntax is not clear */
|
||||
if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
|
||||
parse_attribute(ad);
|
||||
post = type_decl(type, ad, v, td);
|
||||
skip(')');
|
||||
}
|
||||
} else if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
|
||||
/* type identifier */
|
||||
*v = tok;
|
||||
next();
|
||||
} else {
|
||||
/* type identifier */
|
||||
if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
|
||||
*v = tok;
|
||||
next();
|
||||
} else {
|
||||
if (!(td & TYPE_ABSTRACT))
|
||||
expect("identifier");
|
||||
*v = 0;
|
||||
}
|
||||
if (!(td & TYPE_ABSTRACT))
|
||||
expect("identifier");
|
||||
*v = 0;
|
||||
}
|
||||
storage = type->t & VT_STORAGE;
|
||||
type->t &= ~VT_STORAGE;
|
||||
post_type(type, ad, storage);
|
||||
type->t |= storage;
|
||||
post_type(post, ad, storage, 0);
|
||||
if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
|
||||
parse_attribute(ad);
|
||||
|
||||
if (!type1.t)
|
||||
return;
|
||||
/* append type at the end of type1 */
|
||||
type2 = &type1;
|
||||
for(;;) {
|
||||
s = type2->ref;
|
||||
type2 = &s->type;
|
||||
if (!type2->t) {
|
||||
*type2 = *type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*type = type1;
|
||||
type->t |= storage;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* compute the lvalue VT_LVAL_xxx needed to match type t. */
|
||||
|
@ -6924,7 +6917,7 @@ static int decl0(int l, int is_for_loop_init)
|
|||
#if 0
|
||||
{
|
||||
char buf[500];
|
||||
type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
|
||||
type_to_str(buf, sizeof(buf), &type, get_tok_str(v, NULL));
|
||||
printf("type = '%s'\n", buf);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -6,4 +6,38 @@ enum E const *e2;
|
|||
struct S *s;
|
||||
const struct S *s1;
|
||||
struct S const *s2;
|
||||
|
||||
/* Various strangely looking declarators, which are all valid
|
||||
and have to map to the same numbered typedefs. */
|
||||
typedef int (*fptr1)();
|
||||
int f1 (int (), int);
|
||||
typedef int (*fptr2)(int x);
|
||||
int f2 (int (int x), int);
|
||||
typedef int (*fptr3)(int);
|
||||
int f3 (int (int), int);
|
||||
typedef int (*fptr4[4])(int);
|
||||
int f4 (int (*[4])(int), int);
|
||||
typedef int (*fptr5)(fptr1);
|
||||
int f5 (int (int()), fptr1);
|
||||
int f1 (fptr1 fp, int i)
|
||||
{
|
||||
return (*fp)(i);
|
||||
}
|
||||
int f2 (fptr2 fp, int i)
|
||||
{
|
||||
return (*fp)(i);
|
||||
}
|
||||
int f3 (fptr3 fp, int i)
|
||||
{
|
||||
return (*fp)(i);
|
||||
}
|
||||
int f4 (fptr4 fp, int i)
|
||||
{
|
||||
return (*fp[i])(i);
|
||||
}
|
||||
int f5 (fptr5 fp, fptr1 i)
|
||||
{
|
||||
return fp(i);
|
||||
}
|
||||
int f8 (int ([4]), int);
|
||||
int main () { return 0; }
|
||||
|
|
Loading…
Reference in New Issue