aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-10-09 17:28:36 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-10-09 17:28:36 +0200
commit26f670cfb6941221acd19b5ed542a6bba60e963c (patch)
treec351b6144333757f1e8e76cac529a07213713e92
parentb5d46df743be728431fe444008da2c6902cca872 (diff)
parent56b9d0afc2dc70649d157865bf73c78f96621255 (diff)
downloadsparse-26f670cfb6941221acd19b5ed542a6bba60e963c.tar.gz
Merge branch 'usual-conv'
-rw-r--r--evaluate.c67
-rw-r--r--validation/linear/bool-cast-lp32.c1
-rw-r--r--validation/usual-conv-lp32.c11
3 files changed, 47 insertions, 32 deletions
diff --git a/evaluate.c b/evaluate.c
index cfbb6ada..3ff76fa8 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -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
+ */