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
7474 static inline CType *pointed_type(CType *type);
7575 static int is_compatible_types(CType *type1, CType *type2);
7676 static int parse_btype(CType *type, AttributeDef *ad);
77−static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
77+static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);
7878 static void parse_expr_type(CType *type);
7979 static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only);
8080 static 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
35863586 v = 0;
35873587 type1 = btype;
35883588 if (tok != ':') {
3589− type_decl(&type1, &ad1, &v, TYPE_DIRECT | TYPE_ABSTRACT);
3589+ if (tok != ';')
3590+ type_decl(&type1, &ad1, &v, TYPE_DIRECT);
35903591 if (v == 0) {
35913592 if ((type1.t & VT_BTYPE) != VT_STRUCT)
35923593 expect("identifier");
@@ -3964,7 +3965,7 @@ static int asm_label_instr(void) · 371 unmodified lines
39643965 return v;
39653966 }
39663967
3967−static void post_type(CType *type, AttributeDef *ad, int storage)
3968+static int post_type(CType *type, AttributeDef *ad, int storage, int td)
39683969 {
39693970 int n, l, t1, arg_size, align;
39703971 Sym **plast, *s, *first;
@@ -3972,25 +3973,25 @@ static void post_type(CType *type, AttributeDef *ad, int storage) · 1 unmodified line
39723973 CType pt;
39733974
39743975 if (tok == '(') {
3975− /* function declaration */
3976+ /* function type, or recursive declarator (return if so) */
39763977 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;
39783988 first = NULL;
39793989 plast = &first;
39803990 arg_size = 0;
3981− if (tok != ')') {
3991+ if (l) {
39823992 for(;;) {
39833993 /* read param name and compute offset */
39843994 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;
39943995 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
39953996 break;
39963997 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
39983999 tcc_error("parameter declared as void");
39994000 arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE;
40004001 } else {
4001− old_proto:
40024002 n = tok;
40034003 if (n < TOK_UIDENT)
40044004 expect("identifier");
@@ -4017,10 +4017,11 @@ static void post_type(CType *type, AttributeDef *ad, int storage) · 12 unmodified lines
40174017 next();
40184018 break;
40194019 }
4020+ if (l == FUNC_NEW && !parse_btype(&pt, &ad1))
4021+ tcc_error("invalid type");
40204022 }
4021− }
4022− /* if no parameters, then old type prototype */
4023− if (l == 0)
4023+ } else
4024+ /* if no parameters, then old type prototype */
40244025 l = FUNC_OLD;
40254026 skip(')');
40264027 /* 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
40724073 }
40734074 skip(']');
40744075 /* parse next post type */
4075− post_type(type, ad, storage);
4076+ post_type(type, ad, storage, 0);
40764077 if (type->t == VT_FUNC)
40774078 tcc_error("declaration of an array of functions");
40784079 t1 |= type->t & VT_VLA;
@@ -4098,20 +4099,25 @@ static void post_type(CType *type, AttributeDef *ad, int storage) · 19 unmodified lines
40984099 type->t = (t1 ? VT_VLA : VT_ARRAY) | VT_PTR;
40994100 type->ref = s;
41004101 }
4102+ return 1;
41014103 }
41024104
4103−/* Parse a type declaration (except basic type), and return the type
4105+/* Parse a type declarator (except basic type), and return the type
41044106 in 'type'. 'td' is a bitmask indicating which kind of type decl is
41054107 expected. 'type' should contain the basic type. 'ad' is the
41064108 attribute definition of the basic type. It can be modified by
4107− type_decl().
4108− */
4109−static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
4109+ type_decl(). If this (possibly abstract) declarator is a pointer chain
4110+ it returns the innermost pointed to type (equals *type, but is a different
4111+ pointer), otherwise returns type itself, that's used for recursive calls. */
4112+static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td)
41104113 {
4111− Sym *s;
4112− CType type1, *type2;
4114+ CType *post, *ret;
41134115 int qualifiers, storage;
41144116
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;
41154121 while (tok == '*') {
41164122 qualifiers = 0;
41174123 redo:
@@ -4139,51 +4145,38 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td) · 21 unmodified lines
41394145 }
41404146 mk_pointer(type);
41414147 type->t |= qualifiers;
4148+ if (ret == type)
4149+ /* innermost pointed to type is the one for the first derivation */
4150+ ret = pointed_type(type);
41424151 }
41434152
4144− /* recursive type */
4145− /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4146− type1.t = 0; /* XXX: same as int */
41474153 if (tok == '(') {
4148− next();
4149− /* XXX: this is not correct to modify 'ad' at this point, but
4150− the syntax is not clear */
4151− if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
4152− parse_attribute(ad);
4153− type_decl(&type1, ad, v, td);
4154− skip(')');
4154+ /* This is possibly a parameter type list for abstract declarators
4155+ ('int ()'), use post_type for testing this. */
4156+ if (!post_type(type, ad, 0, td)) {
4157+ /* It's not, so it's a nested declarator, and the post operations
4158+ apply to the innermost pointed to type (if any). */
4159+ /* XXX: this is not correct to modify 'ad' at this point, but
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();
41554170 } else {
4156− /* type identifier */
4157− if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
4158− *v = tok;
4159− next();
4160− } else {
4161− if (!(td & TYPE_ABSTRACT))
4162− expect("identifier");
4163− *v = 0;
4164− }
4171+ if (!(td & TYPE_ABSTRACT))
4172+ expect("identifier");
4173+ *v = 0;
41654174 }
4166− storage = type->t & VT_STORAGE;
4167− type->t &= ~VT_STORAGE;
4168− post_type(type, ad, storage);
4169− type->t |= storage;
4175+ post_type(post, ad, storage, 0);
41704176 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
41714177 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;
41864178 type->t |= storage;
4179+ return ret;
41874180 }
41884181
41894182 /* 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
69246917 #if 0
69256918 {
69266919 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));
69286921 printf("type = '%s'\n", buf);
69296922 }
69306923 #endif
tests/tests2/81_types.c+34−0
@@ -6,4 +6,38 @@ enum E const *e2; · 5 unmodified lines
66 struct S *s;
77 const struct S *s1;
88 struct S const *s2;
9+
10+/* Various strangely looking declarators, which are all valid
11+ and have to map to the same numbered typedefs. */
12+typedef int (*fptr1)();
13+int f1 (int (), int);
14+typedef int (*fptr2)(int x);
15+int f2 (int (int x), int);
16+typedef int (*fptr3)(int);
17+int f3 (int (int), int);
18+typedef int (*fptr4[4])(int);
19+int f4 (int (*[4])(int), int);
20+typedef int (*fptr5)(fptr1);
21+int f5 (int (int()), fptr1);
22+int f1 (fptr1 fp, int i)
23+{
24+ return (*fp)(i);
25+}
26+int f2 (fptr2 fp, int i)
27+{
28+ return (*fp)(i);
29+}
30+int f3 (fptr3 fp, int i)
31+{
32+ return (*fp)(i);
33+}
34+int f4 (fptr4 fp, int i)
35+{
36+ return (*fp[i])(i);
37+}
38+int f5 (fptr5 fp, fptr1 i)
39+{
40+ return fp(i);
41+}
42+int f8 (int ([4]), int);
943 int 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