mirror of
https://github.com/frida/tinycc
synced 2025-01-11 22:29:18 +03:00
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).
This commit is contained in:
parent
b1a906b970
commit
34fc6435ee
3
tcc.h
3
tcc.h
@ -387,7 +387,8 @@ struct Attribute {
|
|||||||
mode : 4,
|
mode : 4,
|
||||||
weak : 1,
|
weak : 1,
|
||||||
visibility : 2,
|
visibility : 2,
|
||||||
fill : 8; // 8 bits left to fit well in union below
|
unsigned_enum : 1,
|
||||||
|
fill : 7; // 7 bits left to fit well in union below
|
||||||
};
|
};
|
||||||
|
|
||||||
/* GNUC attribute definition */
|
/* GNUC attribute definition */
|
||||||
|
2
tccasm.c
2
tccasm.c
@ -612,7 +612,7 @@ static void asm_parse_directive(TCCState *s1)
|
|||||||
case TOK_ASMDIR_global:
|
case TOK_ASMDIR_global:
|
||||||
case TOK_ASMDIR_weak:
|
case TOK_ASMDIR_weak:
|
||||||
case TOK_ASMDIR_hidden:
|
case TOK_ASMDIR_hidden:
|
||||||
tok1 = tok;
|
tok1 = tok;
|
||||||
do {
|
do {
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
|
|
||||||
|
42
tccgen.c
42
tccgen.c
@ -2565,13 +2565,20 @@ static int compare_types(CType *type1, CType *type2, int unqualified)
|
|||||||
t1 &= ~VT_DEFSIGN;
|
t1 &= ~VT_DEFSIGN;
|
||||||
t2 &= ~VT_DEFSIGN;
|
t2 &= ~VT_DEFSIGN;
|
||||||
}
|
}
|
||||||
|
/* An enum is compatible with (unsigned) int. Ideally we would
|
||||||
|
store the enums signedness in type->ref.a.<some_bit> and
|
||||||
|
only accept unsigned enums with unsigned int and vice versa.
|
||||||
|
But one of our callers (gen_assign_cast) always strips VT_UNSIGNED
|
||||||
|
from pointer target types, so we can't add it here either. */
|
||||||
if ((t1 & VT_BTYPE) == VT_ENUM) {
|
if ((t1 & VT_BTYPE) == VT_ENUM) {
|
||||||
/* An enum is compatible with (unsigned) int. */
|
t1 = VT_INT;
|
||||||
t1 = VT_INT | (t1 & ~VT_BTYPE);
|
if (type1->ref->a.unsigned_enum)
|
||||||
|
t1 |= VT_UNSIGNED;
|
||||||
}
|
}
|
||||||
if ((t2 & VT_BTYPE) == VT_ENUM) {
|
if ((t2 & VT_BTYPE) == VT_ENUM) {
|
||||||
/* An enum is compatible with (unsigned) int. */
|
t2 = VT_INT;
|
||||||
t2 = VT_INT | (t2 & ~VT_BTYPE);
|
if (type2->ref->a.unsigned_enum)
|
||||||
|
t2 |= VT_UNSIGNED;
|
||||||
}
|
}
|
||||||
/* XXX: bitfields ? */
|
/* XXX: bitfields ? */
|
||||||
if (t1 != t2)
|
if (t1 != t2)
|
||||||
@ -2766,15 +2773,23 @@ static void gen_assign_cast(CType *dt)
|
|||||||
(type2->t & VT_BTYPE) == VT_VOID) {
|
(type2->t & VT_BTYPE) == VT_VOID) {
|
||||||
/* void * can match anything */
|
/* void * can match anything */
|
||||||
} else {
|
} else {
|
||||||
/* exact type match, except for unsigned */
|
/* exact type match, except for qualifiers */
|
||||||
tmp_type1 = *type1;
|
tmp_type1 = *type1;
|
||||||
tmp_type2 = *type2;
|
tmp_type2 = *type2;
|
||||||
tmp_type1.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT |
|
tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
|
||||||
VT_VOLATILE);
|
tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
|
||||||
tmp_type2.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT |
|
if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
|
||||||
VT_VOLATILE);
|
/* Like GCC don't warn by default for merely changes
|
||||||
if (!is_compatible_types(&tmp_type1, &tmp_type2))
|
in pointer target signedness. Do warn for different
|
||||||
tcc_warning("assignment from incompatible pointer type");
|
base types, though, in particular for unsigned enums
|
||||||
|
and signed int targets. */
|
||||||
|
if ((tmp_type1.t & (VT_DEFSIGN | VT_UNSIGNED)) !=
|
||||||
|
(tmp_type2.t & (VT_DEFSIGN | VT_UNSIGNED)) &&
|
||||||
|
(tmp_type1.t & VT_BTYPE) == (tmp_type2.t & VT_BTYPE))
|
||||||
|
;
|
||||||
|
else
|
||||||
|
tcc_warning("assignment from incompatible pointer type");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* check const and volatile */
|
/* check const and volatile */
|
||||||
if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
|
if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
|
||||||
@ -3252,6 +3267,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
|
|||||||
c = 0;
|
c = 0;
|
||||||
/* non empty enums are not allowed */
|
/* non empty enums are not allowed */
|
||||||
if (a == TOK_ENUM) {
|
if (a == TOK_ENUM) {
|
||||||
|
int seen_neg = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
v = tok;
|
v = tok;
|
||||||
if (v < TOK_UIDENT)
|
if (v < TOK_UIDENT)
|
||||||
@ -3265,6 +3281,8 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
|
|||||||
next();
|
next();
|
||||||
c = expr_const();
|
c = expr_const();
|
||||||
}
|
}
|
||||||
|
if (c < 0)
|
||||||
|
seen_neg = 1;
|
||||||
/* enum symbols have static storage */
|
/* enum symbols have static storage */
|
||||||
ss = sym_push(v, &int_type, VT_CONST, c);
|
ss = sym_push(v, &int_type, VT_CONST, c);
|
||||||
ss->type.t |= VT_STATIC;
|
ss->type.t |= VT_STATIC;
|
||||||
@ -3276,6 +3294,8 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
|
|||||||
if (tok == '}')
|
if (tok == '}')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!seen_neg)
|
||||||
|
s->a.unsigned_enum = 1;
|
||||||
s->c = type_size(&int_type, &align);
|
s->c = type_size(&int_type, &align);
|
||||||
skip('}');
|
skip('}');
|
||||||
} else {
|
} else {
|
||||||
|
@ -591,7 +591,7 @@ void enum_test()
|
|||||||
{
|
{
|
||||||
enum test b1;
|
enum test b1;
|
||||||
/* The following should give no warning */
|
/* The following should give no warning */
|
||||||
int *p = &b1;
|
unsigned *p = &b1;
|
||||||
printf("enum:\n%d %d %d %d %d %d\n",
|
printf("enum:\n%d %d %d %d %d %d\n",
|
||||||
E0, E1, E2, E3, E4, E5);
|
E0, E1, E2, E3, E4, E5);
|
||||||
b1 = 1;
|
b1 = 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user