History

Reorganize type parsing

Various corner cases for declarator parsing were incorrect. This reorganizes and fixes it, and somewhat simplifies it as well.

Michael Matz committed 9 years ago

Commit 182367e1 parent 5891fbc2 files · +91 −64Browse files

Unified · Split

2 files
  1. tccgen.c +57 −64
  2. tests/tests2/81_types.c +34 −0
tccgen.c+57−64
@@ -74,7 +74,7 @@ static void gen_cast(CType *type); · 73 unmodified lines
74static inline CType *pointed_type(CType *type);74static inline CType *pointed_type(CType *type);
75static int is_compatible_types(CType *type1, CType *type2);75static int is_compatible_types(CType *type1, CType *type2);
76static int parse_btype(CType *type, AttributeDef *ad);76static int parse_btype(CType *type, AttributeDef *ad);
77static void type_decl(CType *type, AttributeDef *ad, int *v, int td);77static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);
78static void parse_expr_type(CType *type);78static void parse_expr_type(CType *type);
79static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only);79static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only);
80static void block(int *bsym, int *csym, int is_expr);80static void block(int *bsym, int *csym, int is_expr);
@@ -3586,7 +3586,8 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 3505 unmodified lines
3586 v = 0;3586 v = 0;
3587 type1 = btype;3587 type1 = btype;
3588 if (tok != ':') {3588 if (tok != ':') {
3589 type_decl(&type1, &ad1, &v, TYPE_DIRECT | TYPE_ABSTRACT);3589 if (tok != ';')
3590 type_decl(&type1, &ad1, &v, TYPE_DIRECT);
3590 if (v == 0) {3591 if (v == 0) {
3591 if ((type1.t & VT_BTYPE) != VT_STRUCT)3592 if ((type1.t & VT_BTYPE) != VT_STRUCT)
3592 expect("identifier");3593 expect("identifier");
@@ -3964,7 +3965,7 @@ static int asm_label_instr(void) · 371 unmodified lines
3964 return v;3965 return v;
3965}3966}
3966 3967
3967static void post_type(CType *type, AttributeDef *ad, int storage)3968static int post_type(CType *type, AttributeDef *ad, int storage, int td)
3968{3969{
3969 int n, l, t1, arg_size, align;3970 int n, l, t1, arg_size, align;
3970 Sym **plast, *s, *first;3971 Sym **plast, *s, *first;
@@ -3972,25 +3973,25 @@ static void post_type(CType *type, AttributeDef *ad, int storage) · 1 unmodified line
3972 CType pt;3973 CType pt;
3973 3974
3974 if (tok == '(') {3975 if (tok == '(') {
3975 /* function declaration */3976 /* function type, or recursive declarator (return if so) */
3976 next();3977 next();
3977 l = 0;3978 if (td && !(td & TYPE_ABSTRACT))
3979 return 0;
3980 if (tok == ')')
3981 l = 0;
3982 else if (parse_btype(&pt, &ad1))
3983 l = FUNC_NEW;
3984 else if (td)
3985 return 0;
3986 else
3987 l = FUNC_OLD;
3978 first = NULL;3988 first = NULL;
3979 plast = &first;3989 plast = &first;
3980 arg_size = 0;3990 arg_size = 0;
3981 if (tok != ')') {3991 if (l) {
3982 for(;;) {3992 for(;;) {
3983 /* read param name and compute offset */3993 /* read param name and compute offset */
3984 if (l != FUNC_OLD) {3994 if (l != FUNC_OLD) {
3985 if (!parse_btype(&pt, &ad1)) {
3986 if (l) {
3987 tcc_error("invalid type");
3988 } else {
3989 l = FUNC_OLD;
3990 goto old_proto;
3991 }
3992 }
3993 l = FUNC_NEW;
3994 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')3995 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
3995 break;3996 break;
3996 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);3997 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
@@ -3998,7 +3999,6 @@ static void post_type(CType *type, AttributeDef *ad, int storage) · 1 unmodified line
3998 tcc_error("parameter declared as void");3999 tcc_error("parameter declared as void");
3999 arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE;4000 arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE;
4000 } else {4001 } else {
4001 old_proto:
4002 n = tok;4002 n = tok;
4003 if (n < TOK_UIDENT)4003 if (n < TOK_UIDENT)
4004 expect("identifier");4004 expect("identifier");
@@ -4017,10 +4017,11 @@ static void post_type(CType *type, AttributeDef *ad, int storage) · 12 unmodified lines
4017 next();4017 next();
4018 break;4018 break;
4019 }4019 }
4020 if (l == FUNC_NEW && !parse_btype(&pt, &ad1))
4021 tcc_error("invalid type");
4020 }4022 }
4021 }4023 } else
4022 /* if no parameters, then old type prototype */4024 /* if no parameters, then old type prototype */
4023 if (l == 0)
4024 l = FUNC_OLD;4025 l = FUNC_OLD;
4025 skip(')');4026 skip(')');
4026 /* NOTE: const is ignored in returned type as it has a special4027 /* 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) · 45 unmodified lines
4072 }4073 }
4073 skip(']');4074 skip(']');
4074 /* parse next post type */4075 /* parse next post type */
4075 post_type(type, ad, storage);4076 post_type(type, ad, storage, 0);
4076 if (type->t == VT_FUNC)4077 if (type->t == VT_FUNC)
4077 tcc_error("declaration of an array of functions");4078 tcc_error("declaration of an array of functions");
4078 t1 |= type->t & VT_VLA;4079 t1 |= type->t & VT_VLA;
@@ -4098,20 +4099,25 @@ static void post_type(CType *type, AttributeDef *ad, int storage) · 19 unmodified lines
4098 type->t = (t1 ? VT_VLA : VT_ARRAY) | VT_PTR;4099 type->t = (t1 ? VT_VLA : VT_ARRAY) | VT_PTR;
4099 type->ref = s;4100 type->ref = s;
4100 }4101 }
4102 return 1;
4101}4103}
4102 4104
4103/* Parse a type declaration (except basic type), and return the type4105/* Parse a type declarator (except basic type), and return the type
4104 in 'type'. 'td' is a bitmask indicating which kind of type decl is4106 in 'type'. 'td' is a bitmask indicating which kind of type decl is
4105 expected. 'type' should contain the basic type. 'ad' is the4107 expected. 'type' should contain the basic type. 'ad' is the
4106 attribute definition of the basic type. It can be modified by4108 attribute definition of the basic type. It can be modified by
4107 type_decl(). 4109 type_decl(). If this (possibly abstract) declarator is a pointer chain
4108 */4110 it returns the innermost pointed to type (equals *type, but is a different
4109static void type_decl(CType *type, AttributeDef *ad, int *v, int td)4111 pointer), otherwise returns type itself, that's used for recursive calls. */
4112static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td)
4110{4113{
4111 Sym *s;4114 CType *post, *ret;
4112 CType type1, *type2;
4113 int qualifiers, storage;4115 int qualifiers, storage;
4114 4116
4117 /* recursive type, remove storage bits first, apply them later again */
4118 storage = type->t & VT_STORAGE;
4119 type->t &= ~VT_STORAGE;
4120 post = ret = type;
4115 while (tok == '*') {4121 while (tok == '*') {
4116 qualifiers = 0;4122 qualifiers = 0;
4117 redo:4123 redo:
@@ -4139,51 +4145,38 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td) · 21 unmodified lines
4139 }4145 }
4140 mk_pointer(type);4146 mk_pointer(type);
4141 type->t |= qualifiers;4147 type->t |= qualifiers;
4148 if (ret == type)
4149 /* innermost pointed to type is the one for the first derivation */
4150 ret = pointed_type(type);
4142 }4151 }
4143 4152
4144 /* recursive type */
4145 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4146 type1.t = 0; /* XXX: same as int */
4147 if (tok == '(') {4153 if (tok == '(') {
4148 next();4154 /* This is possibly a parameter type list for abstract declarators
4149 /* XXX: this is not correct to modify 'ad' at this point, but4155 ('int ()'), use post_type for testing this. */
4150 the syntax is not clear */4156 if (!post_type(type, ad, 0, td)) {
4151 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)4157 /* It's not, so it's a nested declarator, and the post operations
4152 parse_attribute(ad);4158 apply to the innermost pointed to type (if any). */
4153 type_decl(&type1, ad, v, td);4159 /* XXX: this is not correct to modify 'ad' at this point, but
4154 skip(')');4160 the syntax is not clear */
4161 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
4162 parse_attribute(ad);
4163 post = type_decl(type, ad, v, td);
4164 skip(')');
4165 }
4166 } else if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
4167 /* type identifier */
4168 *v = tok;
4169 next();
4155 } else {4170 } else {
4156 /* type identifier */4171 if (!(td & TYPE_ABSTRACT))
4157 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {4172 expect("identifier");
4158 *v = tok;4173 *v = 0;
4159 next();
4160 } else {
4161 if (!(td & TYPE_ABSTRACT))
4162 expect("identifier");
4163 *v = 0;
4164 }
4165 }4174 }
4166 storage = type->t & VT_STORAGE;4175 post_type(post, ad, storage, 0);
4167 type->t &= ~VT_STORAGE;
4168 post_type(type, ad, storage);
4169 type->t |= storage;
4170 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)4176 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
4171 parse_attribute(ad);4177 parse_attribute(ad);
4172
4173 if (!type1.t)
4174 return;
4175 /* append type at the end of type1 */
4176 type2 = &type1;
4177 for(;;) {
4178 s = type2->ref;
4179 type2 = &s->type;
4180 if (!type2->t) {
4181 *type2 = *type;
4182 break;
4183 }
4184 }
4185 *type = type1;
4186 type->t |= storage;4178 type->t |= storage;
4179 return ret;
4187}4180}
4188 4181
4189/* compute the lvalue VT_LVAL_xxx needed to match type t. */4182/* 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) · 2734 unmodified lines
6924#if 06917#if 0
6925 {6918 {
6926 char buf[500];6919 char buf[500];
6927 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));6920 type_to_str(buf, sizeof(buf), &type, get_tok_str(v, NULL));
6928 printf("type = '%s'\n", buf);6921 printf("type = '%s'\n", buf);
6929 }6922 }
6930#endif6923#endif
tests/tests2/81_types.c+34−0
@@ -6,4 +6,38 @@ enum E const *e2; · 5 unmodified lines
6struct S *s;6struct S *s;
7const struct S *s1;7const struct S *s1;
8struct S const *s2;8struct S const *s2;
9
10/* Various strangely looking declarators, which are all valid
11 and have to map to the same numbered typedefs. */
12typedef int (*fptr1)();
13int f1 (int (), int);
14typedef int (*fptr2)(int x);
15int f2 (int (int x), int);
16typedef int (*fptr3)(int);
17int f3 (int (int), int);
18typedef int (*fptr4[4])(int);
19int f4 (int (*[4])(int), int);
20typedef int (*fptr5)(fptr1);
21int f5 (int (int()), fptr1);
22int f1 (fptr1 fp, int i)
23{
24 return (*fp)(i);
25}
26int f2 (fptr2 fp, int i)
27{
28 return (*fp)(i);
29}
30int f3 (fptr3 fp, int i)
31{
32 return (*fp)(i);
33}
34int f4 (fptr4 fp, int i)
35{
36 return (*fp[i])(i);
37}
38int f5 (fptr5 fp, fptr1 i)
39{
40 return fp(i);
41}
42int f8 (int ([4]), int);
9int main () { return 0; }43int main () { return 0; }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t