diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-10-09 17:28:36 +0200 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-10-09 17:28:36 +0200 |
commit | 26f670cfb6941221acd19b5ed542a6bba60e963c (patch) | |
tree | c351b6144333757f1e8e76cac529a07213713e92 | |
parent | b5d46df743be728431fe444008da2c6902cca872 (diff) | |
parent | 56b9d0afc2dc70649d157865bf73c78f96621255 (diff) | |
download | sparse-26f670cfb6941221acd19b5ed542a6bba60e963c.tar.gz |
Merge branch 'usual-conv'
-rw-r--r-- | evaluate.c | 67 | ||||
-rw-r--r-- | validation/linear/bool-cast-lp32.c | 1 | ||||
-rw-r--r-- | validation/usual-conv-lp32.c | 11 |
3 files changed, 47 insertions, 32 deletions
@@ -164,49 +164,52 @@ static inline struct symbol *integer_promotion(struct symbol *type) } /* - * integer part of usual arithmetic conversions: - * integer promotions are applied - * if left and right are identical, we are done - * if signedness is the same, convert one with lower rank - * unless unsigned argument has rank lower than signed one, convert the - * signed one. - * if signed argument is bigger than unsigned one, convert the unsigned. - * otherwise, convert signed. - * - * Leaving aside the integer promotions, that is equivalent to - * if identical, don't convert - * if left is bigger than right, convert right - * if right is bigger than left, convert right - * otherwise, if signedness is the same, convert one with lower rank - * otherwise convert the signed one. + * After integer promotons: + * If both types are the same + * -> no conversion needed + * If the types have the same signedness (their rank must be different) + * -> convert to the type of the highest rank + * If rank(unsigned type) >= rank(signed type) + * -> convert to the unsigned type + * If size(signed type) > size(unsigned type) + * -> convert to the signed type + * Otherwise + * -> convert to the unsigned type corresponding to the signed type. */ static struct symbol *bigger_int_type(struct symbol *left, struct symbol *right) { + static struct symbol *unsigned_types[] = { + [0] = &uint_ctype, + [1] = &ulong_ctype, + [2] = &ullong_ctype, + [3] = &uint128_ctype, + }; unsigned long lmod, rmod; + struct symbol *stype, *utype; left = integer_promotion(left); right = integer_promotion(right); if (left == right) - goto left; - - if (left->bit_size > right->bit_size) - goto left; - - if (right->bit_size > left->bit_size) - goto right; + return left; lmod = left->ctype.modifiers; rmod = right->ctype.modifiers; - if ((lmod ^ rmod) & MOD_UNSIGNED) { - if (lmod & MOD_UNSIGNED) - goto left; - } else if (left->rank > right->rank) - goto left; -right: - left = right; -left: - return left; + if (((lmod ^ rmod) & MOD_UNSIGNED) == 0) + return (left->rank > right->rank) ? left : right; + if (lmod & MOD_UNSIGNED) { + utype = left; + stype = right; + } else { + stype = left; + utype = right; + } + if (utype->rank >= stype->rank) + return utype; + if (stype->bit_size > utype->bit_size) + return stype; + utype = unsigned_types[stype->rank]; + return utype; } static int same_cast_type(struct symbol *orig, struct symbol *new) @@ -2886,6 +2889,8 @@ static struct symbol *cast_to_bool(struct expression *expr) return NULL; zero = alloc_const_expression(expr->pos, 0); + if (oclass & TYPE_PTR) + zero->ctype = otype; expr->op = SPECIAL_NOTEQUAL; ctype = usual_conversions(expr->op, old, zero, oclass, TYPE_NUM, otype, zero->ctype); diff --git a/validation/linear/bool-cast-lp32.c b/validation/linear/bool-cast-lp32.c index 44a650f4..7aab31dd 100644 --- a/validation/linear/bool-cast-lp32.c +++ b/validation/linear/bool-cast-lp32.c @@ -12,7 +12,6 @@ static _Bool ffun_e(void) { return (_Bool)ffun; } /* * check-name: bool-cast-pointer * check-command: test-linearize -m32 -fdump-ir $file - * check-known-to-fail * * check-output-ignore * check-output-excludes: ptrtu\\. diff --git a/validation/usual-conv-lp32.c b/validation/usual-conv-lp32.c new file mode 100644 index 00000000..7f91288e --- /dev/null +++ b/validation/usual-conv-lp32.c @@ -0,0 +1,11 @@ +extern long l; +extern unsigned int u; + +#if __SIZEOF_LONG__ == __SIZEOF_INT__ +_Static_assert([typeof(l + u)] == [unsigned long], "ulong"); +#endif + +/* + * check-name: usual-conversions + * check-command: sparse -m32 $file + */ |