accept the new C2x typed enums (seems new android-NDK headers are using that now)
Unified · Split
| @@ -2791,6 +2791,13 @@ static int compare_types(CType *type1, CType *type2, int unqualified) · 2790 unmodified lines | ||
| 2791 | 2791 | { |
| 2792 | 2792 | int bt1, t1, t2; |
| 2793 | 2793 | |
| 2794 | + if (IS_ENUM(type1->t)) { | |
| 2795 | + if (IS_ENUM(type2->t)) | |
| 2796 | + return type1->ref == type2->ref; | |
| 2797 | + type1 = &type1->ref->type; | |
| 2798 | + } else if (IS_ENUM(type2->t)) | |
| 2799 | + type2 = &type2->ref->type; | |
| 2800 | + | |
| 2794 | 2801 | t1 = type1->t & VT_TYPE; |
| 2795 | 2802 | t2 = type2->t & VT_TYPE; |
| 2796 | 2803 | if (unqualified) { |
| @@ -2824,10 +2831,6 @@ static int compare_types(CType *type1, CType *type2, int unqualified) · 27 unmodified lines | ||
| 2824 | 2831 | return (type1->ref == type2->ref); |
| 2825 | 2832 | } else if (bt1 == VT_FUNC) { |
| 2826 | 2833 | return is_compatible_func(type1, type2); |
| 2827 | − } else if (IS_ENUM(type1->t) && IS_ENUM(type2->t)) { | |
| 2828 | − /* If both are enums then they must be the same, if only one is then | |
| 2829 | − t1 and t2 must be equal, which was checked above already. */ | |
| 2830 | − return type1->ref == type2->ref; | |
| 2831 | 2834 | } else { |
| 2832 | 2835 | return 1; |
| 2833 | 2836 | } |
| @@ -3191,6 +3194,9 @@ static void gen_cast(CType *type) · 357 unmodified lines | ||
| 3191 | 3194 | if (vtop->type.t & VT_BITFIELD) |
| 3192 | 3195 | gv(RC_INT); |
| 3193 | 3196 | |
| 3197 | + if (IS_ENUM(type->t) && type->ref->c < 0) | |
| 3198 | + tcc_error("cast to incomplete type"); | |
| 3199 | + | |
| 3194 | 3200 | dbt = type->t & (VT_BTYPE | VT_UNSIGNED); |
| 3195 | 3201 | sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED); |
| 3196 | 3202 | if (sbt == VT_FUNC) |
| @@ -3313,9 +3319,6 @@ error: · 116 unmodified lines | ||
| 3313 | 3319 | if (ds == 0 || ss == 0) |
| 3314 | 3320 | goto error; |
| 3315 | 3321 | |
| 3316 | − if (IS_ENUM(type->t) && type->ref->c < 0) | |
| 3317 | − tcc_error("cast to incomplete type"); | |
| 3318 | − | |
| 3319 | 3322 | /* same size and no sign conversion needed */ |
| 3320 | 3323 | if (ds == ss && ds >= 4) |
| 3321 | 3324 | goto done; |
| @@ -4343,7 +4346,7 @@ static void do_Static_assert(void); · 1021 unmodified lines | ||
| 4343 | 4346 | static void struct_decl(CType *type, int u) |
| 4344 | 4347 | { |
| 4345 | 4348 | int v, c, size, align, flexible; |
| 4346 | − int bit_size, bsize, bt; | |
| 4349 | + int bit_size, bsize, bt, ut; | |
| 4347 | 4350 | Sym *s, *ss, **ps; |
| 4348 | 4351 | AttributeDef ad, ad1; |
| 4349 | 4352 | CType type1, btype; |
| @@ -4351,28 +4354,43 @@ static void struct_decl(CType *type, int u) · 1 unmodified line | ||
| 4351 | 4354 | memset(&ad, 0, sizeof ad); |
| 4352 | 4355 | next(); |
| 4353 | 4356 | parse_attribute(&ad); |
| 4354 | − if (tok != '{') { | |
| 4355 | − v = tok; | |
| 4356 | − next(); | |
| 4357 | + | |
| 4358 | + v = 0; | |
| 4359 | + if (tok >= TOK_IDENT) /* struct/enum tag */ | |
| 4360 | + v = tok, next(); | |
| 4361 | + | |
| 4362 | + bt = ut = 0; | |
| 4363 | + if (u == VT_ENUM) { | |
| 4364 | + ut = VT_INT; | |
| 4365 | + if (tok == ':') { /* C2x enum : <type> ... */ | |
| 4366 | + next(); | |
| 4367 | + if (!parse_btype(&btype, &ad1, 0) | |
| 4368 | + || !is_integer_btype(btype.t & VT_BTYPE)) | |
| 4369 | + expect("enum type"); | |
| 4370 | + bt = ut = btype.t & (VT_BTYPE|VT_LONG|VT_UNSIGNED|VT_DEFSIGN); | |
| 4371 | + } | |
| 4372 | + } | |
| 4373 | + | |
| 4374 | + if (v) { | |
| 4357 | 4375 | /* struct already defined ? return it */ |
| 4358 | − if (v < TOK_IDENT) | |
| 4359 | − expect("struct/union/enum name"); | |
| 4360 | 4376 | s = struct_find(v); |
| 4361 | − if (s && (s->sym_scope == local_scope || tok != '{')) { | |
| 4377 | + if (s && (s->sym_scope == local_scope || (tok != '{' && tok != ';'))) { | |
| 4362 | 4378 | if (u == s->type.t) |
| 4363 | 4379 | goto do_decl; |
| 4364 | − if (u == VT_ENUM && IS_ENUM(s->type.t)) | |
| 4380 | + if (u == VT_ENUM && IS_ENUM(s->type.t)) /* XXX: check integral types */ | |
| 4365 | 4381 | goto do_decl; |
| 4366 | − tcc_error("redefinition of '%s'", get_tok_str(v, NULL)); | |
| 4382 | + tcc_error("redeclaration of '%s'", get_tok_str(v, NULL)); | |
| 4367 | 4383 | } |
| 4368 | 4384 | } else { |
| 4385 | + if (tok != '{') | |
| 4386 | + expect("struct/union/enum name"); | |
| 4369 | 4387 | v = anon_sym++; |
| 4370 | 4388 | } |
| 4371 | 4389 | /* Record the original enum/struct/union token. */ |
| 4372 | − type1.t = u == VT_ENUM ? u | VT_INT | VT_UNSIGNED : u; | |
| 4390 | + type1.t = u | ut; | |
| 4373 | 4391 | type1.ref = NULL; |
| 4374 | 4392 | /* we put an undefined size for struct/union */ |
| 4375 | − s = sym_push(v | SYM_STRUCT, &type1, 0, -1); | |
| 4393 | + s = sym_push(v | SYM_STRUCT, &type1, 0, bt ? 0 : -1); | |
| 4376 | 4394 | s->r = 0; /* default alignment is zero as gcc */ |
| 4377 | 4395 | do_decl: |
| 4378 | 4396 | type->t = s->type.t; |
| @@ -4380,7 +4398,8 @@ do_decl: · 1 unmodified line | ||
| 4380 | 4398 | |
| 4381 | 4399 | if (tok == '{') { |
| 4382 | 4400 | next(); |
| 4383 | − if (s->c != -1) | |
| 4401 | + if (s->c != -1 | |
| 4402 | + && !(u == VT_ENUM && s->c == 0)) /* not yet defined typed enum */ | |
| 4384 | 4403 | tcc_error("struct/union/enum already defined"); |
| 4385 | 4404 | s->c = -2; |
| 4386 | 4405 | /* cannot be empty */ |
| @@ -4392,6 +4411,8 @@ do_decl: · 5 unmodified lines | ||
| 4392 | 4411 | t.ref = s; |
| 4393 | 4412 | /* enum symbols have static storage */ |
| 4394 | 4413 | t.t = VT_INT|VT_STATIC|VT_ENUM_VAL; |
| 4414 | + if (bt) | |
| 4415 | + t.t = bt|VT_STATIC|VT_ENUM_VAL; | |
| 4395 | 4416 | for(;;) { |
| 4396 | 4417 | v = tok; |
| 4397 | 4418 | if (v < TOK_UIDENT) |
| @@ -4421,6 +4442,13 @@ do_decl: · 23 unmodified lines | ||
| 4421 | 4442 | break; |
| 4422 | 4443 | } |
| 4423 | 4444 | skip('}'); |
| 4445 | + | |
| 4446 | + if (bt) { | |
| 4447 | + t.t = bt; | |
| 4448 | + s->c = 2; | |
| 4449 | + goto enum_done; | |
| 4450 | + } | |
| 4451 | + | |
| 4424 | 4452 | /* set integral type of the enum */ |
| 4425 | 4453 | t.t = VT_INT; |
| 4426 | 4454 | if (nl >= 0) { |
| @@ -4429,8 +4457,7 @@ do_decl: · 2 unmodified lines | ||
| 4429 | 4457 | t.t |= VT_UNSIGNED; |
| 4430 | 4458 | } else if (pl != (int)pl || nl != (int)nl) |
| 4431 | 4459 | t.t = (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG); |
| 4432 | − s->type.t = type->t = t.t | VT_ENUM; | |
| 4433 | − s->c = 0; | |
| 4460 | + | |
| 4434 | 4461 | /* set type for enum members */ |
| 4435 | 4462 | for (ss = s->next; ss; ss = ss->next) { |
| 4436 | 4463 | ll = ss->enum_val; |
| @@ -4444,6 +4471,10 @@ do_decl: · 7 unmodified lines | ||
| 4444 | 4471 | ss->type.t = (ss->type.t & ~VT_BTYPE) |
| 4445 | 4472 | | (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG); |
| 4446 | 4473 | } |
| 4474 | + s->c = 1; | |
| 4475 | + enum_done: | |
| 4476 | + s->type.t = type->t = t.t | VT_ENUM; | |
| 4477 | + | |
| 4447 | 4478 | } else { |
| 4448 | 4479 | c = 0; |
| 4449 | 4480 | flexible = 0; |