mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-27 06:10:06 +08:00
Reorganize type parsing
Various corner cases for declarator parsing were incorrect. This reorganizes and fixes it, and somewhat simplifies it as well.
This commit is contained in:
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 inline CType *pointed_type(CType *type);
|
||||||
static int is_compatible_types(CType *type1, CType *type2);
|
static int is_compatible_types(CType *type1, CType *type2);
|
||||||
static int parse_btype(CType *type, AttributeDef *ad);
|
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 parse_expr_type(CType *type);
|
||||||
static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only);
|
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 block(int *bsym, int *csym, int is_expr);
|
||||||
@ -3586,7 +3586,8 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
|
|||||||
v = 0;
|
v = 0;
|
||||||
type1 = btype;
|
type1 = btype;
|
||||||
if (tok != ':') {
|
if (tok != ':') {
|
||||||
type_decl(&type1, &ad1, &v, TYPE_DIRECT | TYPE_ABSTRACT);
|
if (tok != ';')
|
||||||
|
type_decl(&type1, &ad1, &v, TYPE_DIRECT);
|
||||||
if (v == 0) {
|
if (v == 0) {
|
||||||
if ((type1.t & VT_BTYPE) != VT_STRUCT)
|
if ((type1.t & VT_BTYPE) != VT_STRUCT)
|
||||||
expect("identifier");
|
expect("identifier");
|
||||||
@ -3964,7 +3965,7 @@ static int asm_label_instr(void)
|
|||||||
return v;
|
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;
|
int n, l, t1, arg_size, align;
|
||||||
Sym **plast, *s, *first;
|
Sym **plast, *s, *first;
|
||||||
@ -3972,25 +3973,25 @@ static void post_type(CType *type, AttributeDef *ad, int storage)
|
|||||||
CType pt;
|
CType pt;
|
||||||
|
|
||||||
if (tok == '(') {
|
if (tok == '(') {
|
||||||
/* function declaration */
|
/* function type, or recursive declarator (return if so) */
|
||||||
next();
|
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;
|
first = NULL;
|
||||||
plast = &first;
|
plast = &first;
|
||||||
arg_size = 0;
|
arg_size = 0;
|
||||||
if (tok != ')') {
|
if (l) {
|
||||||
for(;;) {
|
for(;;) {
|
||||||
/* read param name and compute offset */
|
/* read param name and compute offset */
|
||||||
if (l != FUNC_OLD) {
|
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 == ')')
|
if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
|
||||||
break;
|
break;
|
||||||
type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
|
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");
|
tcc_error("parameter declared as void");
|
||||||
arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE;
|
arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE;
|
||||||
} else {
|
} else {
|
||||||
old_proto:
|
|
||||||
n = tok;
|
n = tok;
|
||||||
if (n < TOK_UIDENT)
|
if (n < TOK_UIDENT)
|
||||||
expect("identifier");
|
expect("identifier");
|
||||||
@ -4017,10 +4017,11 @@ static void post_type(CType *type, AttributeDef *ad, int storage)
|
|||||||
next();
|
next();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (l == FUNC_NEW && !parse_btype(&pt, &ad1))
|
||||||
|
tcc_error("invalid type");
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
/* if no parameters, then old type prototype */
|
/* if no parameters, then old type prototype */
|
||||||
if (l == 0)
|
|
||||||
l = FUNC_OLD;
|
l = FUNC_OLD;
|
||||||
skip(')');
|
skip(')');
|
||||||
/* NOTE: const is ignored in returned type as it has a special
|
/* 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(']');
|
skip(']');
|
||||||
/* parse next post type */
|
/* parse next post type */
|
||||||
post_type(type, ad, storage);
|
post_type(type, ad, storage, 0);
|
||||||
if (type->t == VT_FUNC)
|
if (type->t == VT_FUNC)
|
||||||
tcc_error("declaration of an array of functions");
|
tcc_error("declaration of an array of functions");
|
||||||
t1 |= type->t & VT_VLA;
|
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->t = (t1 ? VT_VLA : VT_ARRAY) | VT_PTR;
|
||||||
type->ref = s;
|
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
|
in 'type'. 'td' is a bitmask indicating which kind of type decl is
|
||||||
expected. 'type' should contain the basic type. 'ad' is the
|
expected. 'type' should contain the basic type. 'ad' is the
|
||||||
attribute definition of the basic type. It can be modified by
|
attribute definition of the basic type. It can be modified by
|
||||||
type_decl().
|
type_decl(). If this (possibly abstract) declarator is a pointer chain
|
||||||
*/
|
it returns the innermost pointed to type (equals *type, but is a different
|
||||||
static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
|
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 *post, *ret;
|
||||||
CType type1, *type2;
|
|
||||||
int qualifiers, storage;
|
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 == '*') {
|
while (tok == '*') {
|
||||||
qualifiers = 0;
|
qualifiers = 0;
|
||||||
redo:
|
redo:
|
||||||
@ -4139,51 +4145,38 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
|
|||||||
}
|
}
|
||||||
mk_pointer(type);
|
mk_pointer(type);
|
||||||
type->t |= qualifiers;
|
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 == '(') {
|
if (tok == '(') {
|
||||||
next();
|
/* This is possibly a parameter type list for abstract declarators
|
||||||
/* XXX: this is not correct to modify 'ad' at this point, but
|
('int ()'), use post_type for testing this. */
|
||||||
the syntax is not clear */
|
if (!post_type(type, ad, 0, td)) {
|
||||||
if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
|
/* It's not, so it's a nested declarator, and the post operations
|
||||||
parse_attribute(ad);
|
apply to the innermost pointed to type (if any). */
|
||||||
type_decl(&type1, ad, v, td);
|
/* XXX: this is not correct to modify 'ad' at this point, but
|
||||||
skip(')');
|
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 {
|
} else {
|
||||||
/* type identifier */
|
if (!(td & TYPE_ABSTRACT))
|
||||||
if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
|
expect("identifier");
|
||||||
*v = tok;
|
*v = 0;
|
||||||
next();
|
|
||||||
} else {
|
|
||||||
if (!(td & TYPE_ABSTRACT))
|
|
||||||
expect("identifier");
|
|
||||||
*v = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
storage = type->t & VT_STORAGE;
|
post_type(post, ad, storage, 0);
|
||||||
type->t &= ~VT_STORAGE;
|
|
||||||
post_type(type, ad, storage);
|
|
||||||
type->t |= storage;
|
|
||||||
if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
|
if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
|
||||||
parse_attribute(ad);
|
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;
|
type->t |= storage;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compute the lvalue VT_LVAL_xxx needed to match type t. */
|
/* 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
|
#if 0
|
||||||
{
|
{
|
||||||
char buf[500];
|
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);
|
printf("type = '%s'\n", buf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,4 +6,38 @@ enum E const *e2;
|
|||||||
struct S *s;
|
struct S *s;
|
||||||
const struct S *s1;
|
const struct S *s1;
|
||||||
struct S const *s2;
|
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; }
|
int main () { return 0; }
|
||||||
|
Loading…
Reference in New Issue
Block a user