Fix type completion for array types as well

like qualifier merging the array sizes are merged as well
for the operands of ?:, and they must not statically influence
the types of decls.

Also fix some style problems, spaces aren't stinky :)
This commit is contained in:
Michael Matz 2018-11-30 23:43:30 +01:00
parent f7779efe58
commit c4787e3626
2 changed files with 56 additions and 34 deletions

View File

@ -2097,8 +2097,8 @@ static inline int is_null_pointer(SValue *p)
((p->type.t & VT_BTYPE) == VT_LLONG && p->c.i == 0) || ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.i == 0) ||
((p->type.t & VT_BTYPE) == VT_PTR && ((p->type.t & VT_BTYPE) == VT_PTR &&
(PTR_SIZE == 4 ? (uint32_t)p->c.i == 0 : p->c.i == 0) && (PTR_SIZE == 4 ? (uint32_t)p->c.i == 0 : p->c.i == 0) &&
((pointed_type(&p->type)->t&VT_BTYPE)==VT_VOID) && ((pointed_type(&p->type)->t & VT_BTYPE) == VT_VOID) &&
0==(pointed_type(&p->type)->t&(VT_CONSTANT|VT_VOLATILE)) 0 == (pointed_type(&p->type)->t & (VT_CONSTANT | VT_VOLATILE))
); );
} }
static inline int is_integer_btype(int bt) static inline int is_integer_btype(int bt)
@ -2823,7 +2823,7 @@ static int compare_types(CType *type1, CType *type2, int unqualified)
if (t1 != t2) if (t1 != t2)
return 0; return 0;
/* test more complicated cases */ /* test more complicated cases */
bt1 = t1 & (VT_BTYPE | (unqualified ? 0 : VT_ARRAY) ); bt1 = t1 & (VT_BTYPE | VT_ARRAY);
if (bt1 == VT_PTR) { if (bt1 == VT_PTR) {
type1 = pointed_type(type1); type1 = pointed_type(type1);
type2 = pointed_type(type2); type2 = pointed_type(type2);
@ -5565,10 +5565,9 @@ static void expr_cond(void)
if (!g) if (!g)
gexpr(); gexpr();
if ( ((type1=vtop->type).t&VT_BTYPE)==VT_FUNC ) { if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
mk_pointer(&vtop->type); mk_pointer(&vtop->type);
type1=vtop->type; type1 = vtop->type;
}
sv = *vtop; /* save value to handle it later */ sv = *vtop; /* save value to handle it later */
vtop--; /* no vpop so that FP stack is not flushed */ vtop--; /* no vpop so that FP stack is not flushed */
skip(':'); skip(':');
@ -5586,10 +5585,9 @@ static void expr_cond(void)
if (c == 1) if (c == 1)
nocode_wanted--; nocode_wanted--;
if ( ((type2=vtop->type).t&VT_BTYPE)==VT_FUNC ) { if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
mk_pointer(&vtop->type); mk_pointer(&vtop->type);
type2=vtop->type; type2=vtop->type;
}
t1 = type1.t; t1 = type1.t;
bt1 = t1 & VT_BTYPE; bt1 = t1 & VT_BTYPE;
t2 = type2.t; t2 = type2.t;
@ -5600,7 +5598,7 @@ static void expr_cond(void)
/* cast operands to correct type according to ISOC rules */ /* cast operands to correct type according to ISOC rules */
if (bt1 == VT_VOID || bt2 == VT_VOID) { if (bt1 == VT_VOID || bt2 == VT_VOID) {
type.t = VT_VOID; /* NOTE: as an extension, we accept void on only one side */ type.t = VT_VOID; /* NOTE: as an extension, we accept void on only one side */
}else if (is_float(bt1) || is_float(bt2)) { } else if (is_float(bt1) || is_float(bt2)) {
if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) { if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
type.t = VT_LDOUBLE; type.t = VT_LDOUBLE;
@ -5626,33 +5624,48 @@ static void expr_cond(void)
is the other. */ is the other. */
if (is_null_pointer (vtop)) type = type1; if (is_null_pointer (vtop)) type = type1;
else if (is_null_pointer (&sv)) type = type2; else if (is_null_pointer (&sv)) type = type2;
else{ else if (bt1 != bt2)
int pbt1, pbt2; tcc_error("incompatible types in conditional expressions");
if (bt1!=bt2) else {
tcc_error("incompatible types in conditional expressions"); CType *pt1 = pointed_type(&type1);
pbt1 = (pointed_type(&type1)->t&VT_BTYPE); CType *pt2 = pointed_type(&type2);
pbt2 = (pointed_type(&type2)->t&VT_BTYPE); int pbt1 = pt1->t & VT_BTYPE;
/*pointers to void get preferred, otherwise the pointed to types minus qualifs should be compatible*/ int pbt2 = pt2->t & VT_BTYPE;
type = (pbt1==VT_VOID) ? type1 : type2; int newquals, copied = 0;
if (pbt1!=VT_VOID && pbt2!=VT_VOID){ /* pointers to void get preferred, otherwise the
if(!compare_types(pointed_type(&type1), pointed_type(&type2),1/*unqualif*/)) pointed to types minus qualifs should be compatible */
type = (pbt1 == VT_VOID) ? type1 : type2;
if (pbt1 != VT_VOID && pbt2 != VT_VOID) {
if(!compare_types(pt1, pt2, 1/*unqualif*/))
tcc_warning("pointer type mismatch in conditional expression\n"); tcc_warning("pointer type mismatch in conditional expression\n");
} }
{ /*copy the pointer target symbol*/ /* combine qualifs */
Sym *s; newquals = ((pt1->t | pt2->t) & (VT_CONSTANT | VT_VOLATILE));
s = sym_push(SYM_FIELD, pointed_type(&type), 0, -1); if ((~pointed_type(&type)->t & (VT_CONSTANT | VT_VOLATILE))
type.t = VT_PTR | (type.t & VT_STORAGE); & newquals)
type.ref = s; {
} /* copy the pointer target symbol */
/*qualifs combine*/ type.ref = sym_push(SYM_FIELD, &type.ref->type,
pointed_type(&type)->t |= 0 0, type.ref->c);
|(pointed_type(&type1)->t&(VT_CONSTANT|VT_VOLATILE)) copied = 1;
|(pointed_type(&type2)->t&(VT_CONSTANT|VT_VOLATILE)); pointed_type(&type)->t |= newquals;
/*pointers to incomplete arrays get converted to pointers to completed ones if possible*/ }
if ( (pointed_type(&type1)->t&VT_ARRAY) ) /* pointers to incomplete arrays get converted to
pointers to completed ones if possible */
if (pt1->t & VT_ARRAY
&& pt2->t & VT_ARRAY
&& pointed_type(&type)->ref->c < 0
&& (pt1->ref->c > 0 || pt2->ref->c > 0))
{
if (!copied)
type.ref = sym_push(SYM_FIELD, &type.ref->type,
0, type.ref->c);
pointed_type(&type)->ref =
sym_push(SYM_FIELD, &pointed_type(&type)->ref->type,
0, pointed_type(&type)->ref->c);
pointed_type(&type)->ref->c = pointed_type(&type)->ref->c =
0<pointed_type(&type1)->ref->c ? 0 < pt1->ref->c ? pt1->ref->c : pt2->ref->c;
pointed_type(&type1)->ref->c : pointed_type(&type2)->ref->c; }
} }
} else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) { } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
/* XXX: test structure compatibility */ /* XXX: test structure compatibility */

View File

@ -96,11 +96,20 @@ int main()
(void)(sizeof(struct { int x:_Generic( 0?(int (*)[])0 : (int (*)[4])0, int (*)[4]:+1, int (*)[5]:(void)0); })); (void)(sizeof(struct { int x:_Generic( 0?(int (*)[])0 : (int (*)[4])0, int (*)[4]:+1, int (*)[5]:(void)0); }));
{ {
/* completion shouldn't affect the type of decl */
char **argv; char **argv;
_Generic(argv, char**: (void)0); _Generic(argv, char**: (void)0);
_Generic(0?(char const*)0:argv[0], char const*: (void)0); _Generic(0?(char const*)0:argv[0], char const*: (void)0);
_Generic(argv, char**: (void)0); _Generic(argv, char**: (void)0);
} }
{
extern int (*ar)[];
(void)(sizeof(struct { int x:_Generic( 0?(int (*)[4])0 : (int (*)[])0, int (*)[4]:+1, int (*)[5]:(void)0); }));
(void)(sizeof(struct { int x:_Generic( 0?(int (*)[])0 : (int (*)[4])0, int (*)[4]:+1, int (*)[5]:(void)0); }));
(void)(sizeof(struct { int x:_Generic( 0?ar : (int (*)[4])0, int (*)[4]:+1, int (*)[5]:(void)0); }));
(void)(sizeof(struct { int x:_Generic( 0?(int (*)[4])0 : ar, int (*)[4]:+1, int (*)[5]:(void)0); }));
(void)(sizeof(struct { int x:_Generic( 0?(int (*)[5])0 : ar, int (*)[5]:+1, int (*)[4]:(void)0); }));
}
return 0; return 0;
} }