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
387387 mode : 4,
388388 weak : 1,
389389 visibility : 2,
390− fill : 8; // 8 bits left to fit well in union below
390+ unsigned_enum : 1,
391+ fill : 7; // 7 bits left to fit well in union below
391392 };
392393
393394 /* GNUC attribute definition */
tccasm.c+1−1
@@ -612,7 +612,7 @@ static void asm_parse_directive(TCCState *s1) · 611 unmodified lines
612612 case TOK_ASMDIR_global:
613613 case TOK_ASMDIR_weak:
614614 case TOK_ASMDIR_hidden:
615− tok1 = tok;
615+ tok1 = tok;
616616 do {
617617 Sym *sym;
618618
tccgen.c+31−11
@@ -2565,13 +2565,20 @@ static int compare_types(CType *type1, CType *type2, int unqualified) · 2564 unmodified lines
25652565 t1 &= ~VT_DEFSIGN;
25662566 t2 &= ~VT_DEFSIGN;
25672567 }
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. */
25682573 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;
25712577 }
25722578 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;
25752582 }
25762583 /* XXX: bitfields ? */
25772584 if (t1 != t2)
@@ -2766,15 +2773,23 @@ static void gen_assign_cast(CType *dt) · 188 unmodified lines
27662773 (type2->t & VT_BTYPE) == VT_VOID) {
27672774 /* void * can match anything */
27682775 } else {
2769− /* exact type match, except for unsigned */
2776+ /* exact type match, except for qualifiers */
27702777 tmp_type1 = *type1;
27712778 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+ }
27782793 }
27792794 /* check const and volatile */
27802795 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
32523267 c = 0;
32533268 /* non empty enums are not allowed */
32543269 if (a == TOK_ENUM) {
3270+ int seen_neg = 0;
32553271 for(;;) {
32563272 v = tok;
32573273 if (v < TOK_UIDENT)
@@ -3265,6 +3281,8 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 7 unmodified lines
32653281 next();
32663282 c = expr_const();
32673283 }
3284+ if (c < 0)
3285+ seen_neg = 1;
32683286 /* enum symbols have static storage */
32693287 ss = sym_push(v, &int_type, VT_CONST, c);
32703288 ss->type.t |= VT_STATIC;
@@ -3276,6 +3294,8 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 5 unmodified lines
32763294 if (tok == '}')
32773295 break;
32783296 }
3297+ if (!seen_neg)
3298+ s->a.unsigned_enum = 1;
32793299 s->c = type_size(&int_type, &align);
32803300 skip('}');
32813301 } else {
tests/tcctest.c+1−1
@@ -591,7 +591,7 @@ void enum_test() · 590 unmodified lines
591591 {
592592 enum test b1;
593593 /* The following should give no warning */
594− int *p = &b1;
594+ unsigned *p = &b1;
595595 printf("enum:\n%d %d %d %d %d %d\n",
596596 E0, E1, E2, E3, E4, E5);
597597 b1 = 1;