| @@ -2565,13 +2565,20 @@ static int compare_types(CType *type1, CType *type2, int unqualified) · 2564 unmodified lines |
| 2565 | 2565 | t1 &= ~VT_DEFSIGN; |
| 2566 | 2566 | t2 &= ~VT_DEFSIGN; |
| 2567 | 2567 | } |
| 2568 | + /* An enum is compatible with (unsigned) int. Ideally we would |
| 2569 | + store the enums signedness in type->ref.a.<some_bit> and |
| 2570 | + only accept unsigned enums with unsigned int and vice versa. |
| 2571 | + But one of our callers (gen_assign_cast) always strips VT_UNSIGNED |
| 2572 | + from pointer target types, so we can't add it here either. */ |
| 2568 | 2573 | if ((t1 & VT_BTYPE) == VT_ENUM) { |
| 2569 | | − /* An enum is compatible with (unsigned) int. */ |
| 2570 | | − t1 = VT_INT | (t1 & ~VT_BTYPE); |
| 2574 | + t1 = VT_INT; |
| 2575 | + if (type1->ref->a.unsigned_enum) |
| 2576 | + t1 |= VT_UNSIGNED; |
| 2571 | 2577 | } |
| 2572 | 2578 | if ((t2 & VT_BTYPE) == VT_ENUM) { |
| 2573 | | − /* An enum is compatible with (unsigned) int. */ |
| 2574 | | − t2 = VT_INT | (t2 & ~VT_BTYPE); |
| 2579 | + t2 = VT_INT; |
| 2580 | + if (type2->ref->a.unsigned_enum) |
| 2581 | + t2 |= VT_UNSIGNED; |
| 2575 | 2582 | } |
| 2576 | 2583 | /* XXX: bitfields ? */ |
| 2577 | 2584 | if (t1 != t2) |
| @@ -2766,15 +2773,23 @@ static void gen_assign_cast(CType *dt) · 188 unmodified lines |
| 2766 | 2773 | (type2->t & VT_BTYPE) == VT_VOID) { |
| 2767 | 2774 | /* void * can match anything */ |
| 2768 | 2775 | } else { |
| 2769 | | − /* exact type match, except for unsigned */ |
| 2776 | + /* exact type match, except for qualifiers */ |
| 2770 | 2777 | tmp_type1 = *type1; |
| 2771 | 2778 | tmp_type2 = *type2; |
| 2772 | | − tmp_type1.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT | |
| 2773 | | − VT_VOLATILE); |
| 2774 | | − tmp_type2.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT | |
| 2775 | | − VT_VOLATILE); |
| 2776 | | − if (!is_compatible_types(&tmp_type1, &tmp_type2)) |
| 2777 | | − tcc_warning("assignment from incompatible pointer type"); |
| 2779 | + tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE); |
| 2780 | + tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE); |
| 2781 | + if (!is_compatible_types(&tmp_type1, &tmp_type2)) { |
| 2782 | + /* Like GCC don't warn by default for merely changes |
| 2783 | + in pointer target signedness. Do warn for different |
| 2784 | + base types, though, in particular for unsigned enums |
| 2785 | + and signed int targets. */ |
| 2786 | + if ((tmp_type1.t & (VT_DEFSIGN | VT_UNSIGNED)) != |
| 2787 | + (tmp_type2.t & (VT_DEFSIGN | VT_UNSIGNED)) && |
| 2788 | + (tmp_type1.t & VT_BTYPE) == (tmp_type2.t & VT_BTYPE)) |
| 2789 | + ; |
| 2790 | + else |
| 2791 | + tcc_warning("assignment from incompatible pointer type"); |
| 2792 | + } |
| 2778 | 2793 | } |
| 2779 | 2794 | /* check const and volatile */ |
| 2780 | 2795 | if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) || |
| @@ -3252,6 +3267,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 471 unmodified lines |
| 3252 | 3267 | c = 0; |
| 3253 | 3268 | /* non empty enums are not allowed */ |
| 3254 | 3269 | if (a == TOK_ENUM) { |
| 3270 | + int seen_neg = 0; |
| 3255 | 3271 | for(;;) { |
| 3256 | 3272 | v = tok; |
| 3257 | 3273 | if (v < TOK_UIDENT) |
| @@ -3265,6 +3281,8 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 7 unmodified lines |
| 3265 | 3281 | next(); |
| 3266 | 3282 | c = expr_const(); |
| 3267 | 3283 | } |
| 3284 | + if (c < 0) |
| 3285 | + seen_neg = 1; |
| 3268 | 3286 | /* enum symbols have static storage */ |
| 3269 | 3287 | ss = sym_push(v, &int_type, VT_CONST, c); |
| 3270 | 3288 | ss->type.t |= VT_STATIC; |
| @@ -3276,6 +3294,8 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 5 unmodified lines |
| 3276 | 3294 | if (tok == '}') |
| 3277 | 3295 | break; |
| 3278 | 3296 | } |
| 3297 | + if (!seen_neg) |
| 3298 | + s->a.unsigned_enum = 1; |
| 3279 | 3299 | s->c = type_size(&int_type, &align); |
| 3280 | 3300 | skip('}'); |
| 3281 | 3301 | } else { |