History

enums and ints are compatible

But like GCC do warn about changes in signedness. The latter leads to some changes in gen_assign_cast to not also warn about unsigned* = int* (where GCC warns, but only with extra warnings).

Michael Matz committed 10 years ago

Commit 34fc6431 parent b1a906b4 files · +35 −14Browse files

Unified · Split

4 files
  1. tcc.h +2 −1
  2. tccasm.c +1 −1
  3. tccgen.c +31 −11
  4. tests/tcctest.c +1 −1
tcc.h+2−1
@@ -387,7 +387,8 @@ struct Attribute { · 386 unmodified lines
387 mode : 4,387 mode : 4,
388 weak : 1,388 weak : 1,
389 visibility : 2,389 visibility : 2,
390 fill : 8; // 8 bits left to fit well in union below390 unsigned_enum : 1,
391 fill : 7; // 7 bits left to fit well in union below
391};392};
392 393
393/* GNUC attribute definition */394/* GNUC attribute definition */
tccasm.c+1−1
@@ -612,7 +612,7 @@ static void asm_parse_directive(TCCState *s1) · 611 unmodified lines
612 case TOK_ASMDIR_global:612 case TOK_ASMDIR_global:
613 case TOK_ASMDIR_weak:613 case TOK_ASMDIR_weak:
614 case TOK_ASMDIR_hidden:614 case TOK_ASMDIR_hidden:
615 tok1 = tok;615 tok1 = tok;
616 do { 616 do {
617 Sym *sym;617 Sym *sym;
618 618
tccgen.c+31−11
@@ -2565,13 +2565,20 @@ static int compare_types(CType *type1, CType *type2, int unqualified) · 2564 unmodified lines
2565 t1 &= ~VT_DEFSIGN;2565 t1 &= ~VT_DEFSIGN;
2566 t2 &= ~VT_DEFSIGN;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 if ((t1 & VT_BTYPE) == VT_ENUM) {2573 if ((t1 & VT_BTYPE) == VT_ENUM) {
2569 /* An enum is compatible with (unsigned) int. */2574 t1 = VT_INT;
2570 t1 = VT_INT | (t1 & ~VT_BTYPE);2575 if (type1->ref->a.unsigned_enum)
2576 t1 |= VT_UNSIGNED;
2571 }2577 }
2572 if ((t2 & VT_BTYPE) == VT_ENUM) {2578 if ((t2 & VT_BTYPE) == VT_ENUM) {
2573 /* An enum is compatible with (unsigned) int. */2579 t2 = VT_INT;
2574 t2 = VT_INT | (t2 & ~VT_BTYPE);2580 if (type2->ref->a.unsigned_enum)
2581 t2 |= VT_UNSIGNED;
2575 }2582 }
2576 /* XXX: bitfields ? */2583 /* XXX: bitfields ? */
2577 if (t1 != t2)2584 if (t1 != t2)
@@ -2766,15 +2773,23 @@ static void gen_assign_cast(CType *dt) · 188 unmodified lines
2766 (type2->t & VT_BTYPE) == VT_VOID) {2773 (type2->t & VT_BTYPE) == VT_VOID) {
2767 /* void * can match anything */2774 /* void * can match anything */
2768 } else {2775 } else {
2769 /* exact type match, except for unsigned */2776 /* exact type match, except for qualifiers */
2770 tmp_type1 = *type1;2777 tmp_type1 = *type1;
2771 tmp_type2 = *type2;2778 tmp_type2 = *type2;
2772 tmp_type1.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT |2779 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
2773 VT_VOLATILE);2780 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
2774 tmp_type2.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT |2781 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
2775 VT_VOLATILE);2782 /* Like GCC don't warn by default for merely changes
2776 if (!is_compatible_types(&tmp_type1, &tmp_type2))2783 in pointer target signedness. Do warn for different
2777 tcc_warning("assignment from incompatible pointer type");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 /* check const and volatile */2794 /* check const and volatile */
2780 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||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 c = 0;3267 c = 0;
3253 /* non empty enums are not allowed */3268 /* non empty enums are not allowed */
3254 if (a == TOK_ENUM) {3269 if (a == TOK_ENUM) {
3270 int seen_neg = 0;
3255 for(;;) {3271 for(;;) {
3256 v = tok;3272 v = tok;
3257 if (v < TOK_UIDENT)3273 if (v < TOK_UIDENT)
@@ -3265,6 +3281,8 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 7 unmodified lines
3265 next();3281 next();
3266 c = expr_const();3282 c = expr_const();
3267 }3283 }
3284 if (c < 0)
3285 seen_neg = 1;
3268 /* enum symbols have static storage */3286 /* enum symbols have static storage */
3269 ss = sym_push(v, &int_type, VT_CONST, c);3287 ss = sym_push(v, &int_type, VT_CONST, c);
3270 ss->type.t |= VT_STATIC;3288 ss->type.t |= VT_STATIC;
@@ -3276,6 +3294,8 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 5 unmodified lines
3276 if (tok == '}')3294 if (tok == '}')
3277 break;3295 break;
3278 }3296 }
3297 if (!seen_neg)
3298 s->a.unsigned_enum = 1;
3279 s->c = type_size(&int_type, &align);3299 s->c = type_size(&int_type, &align);
3280 skip('}');3300 skip('}');
3281 } else {3301 } else {
tests/tcctest.c+1−1
@@ -591,7 +591,7 @@ void enum_test() · 590 unmodified lines
591{591{
592 enum test b1;592 enum test b1;
593 /* The following should give no warning */593 /* The following should give no warning */
594 int *p = &b1;594 unsigned *p = &b1;
595 printf("enum:\n%d %d %d %d %d %d\n",595 printf("enum:\n%d %d %d %d %d %d\n",
596 E0, E1, E2, E3, E4, E5);596 E0, E1, E2, E3, E4, E5);
597 b1 = 1;597 b1 = 1;