aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-06-20 17:50:04 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-06-21 11:28:40 +0200
commit9e34da46b99e1e43ed40ec019cce8c06c22eb3fa (patch)
treedd9302c738bcec49bb7244c7e860f4b820599d6b
parent657ea654866b18a368b220bba272b17369b78fe4 (diff)
downloadsparse-9e34da46b99e1e43ed40ec019cce8c06c22eb3fa.tar.gz
fix: __builtin_bswap{16,32,64}() constantness
When expanding those builtins, we directly excludes a non-constant arg (via the expression expansion cost) and the to retrieve the value we use const_expression_value(). But const_expression_value() is to be used for expressions that qualify as 'integer constant expression' as per the C standard. However we want to be able to use this builtin with all integer expressions having a known value at compile time, even those not qualified as true 'integer constant expression'. Fix this by using get_expression_value_silent() instead of const_expression_value(). Note: this bug was found by testing sparse on the git tree on ARM64. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com> Acked-by: Christopher Li <sparse@chrisli.org>
-rw-r--r--builtin.c4
-rw-r--r--validation/builtin-bswap-constant.c6
2 files changed, 9 insertions, 1 deletions
diff --git a/builtin.c b/builtin.c
index 904a6c52..bfadc87f 100644
--- a/builtin.c
+++ b/builtin.c
@@ -180,13 +180,15 @@ static struct symbol_op choose_op = {
/* The argument is constant and valid if the cost is zero */
static int expand_bswap(struct expression *expr, int cost)
{
+ struct expression *arg;
long long val;
if (cost)
return cost;
/* the arguments number & type have already been checked */
- val = const_expression_value(first_expression(expr->args));
+ arg = first_expression(expr->args);
+ val = get_expression_value_silent(arg);
switch (expr->ctype->bit_size) {
case 16: expr->value = bswap16(val); break;
case 32: expr->value = bswap32(val); break;
diff --git a/validation/builtin-bswap-constant.c b/validation/builtin-bswap-constant.c
index 4560f67e..18574d4c 100644
--- a/validation/builtin-bswap-constant.c
+++ b/validation/builtin-bswap-constant.c
@@ -16,6 +16,12 @@ unsigned long long bswap64(void)
return __builtin_bswap64(0x123456789abcdef0ULL);
}
+unsigned int half_constant(void);
+unsigned int half_constant(void)
+{
+ int v = 0x12345678;
+ return __builtin_bswap32(v);
+}
/*
* check-name: builtin-bswap-constant
* check-command: test-linearize $file