Typewisely, sparse process __builtin_expect() as: 1) returning 'int' 2) taking any type in first & second arg 3) returning exactly its first argument, silently, even if this conflicts with 1). but this doesn't match with how gcc declare it: long __builtin_expect(long, long); Fix this by giving the proper prototype to this builtin and removing the bogus 'returns an int'. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- builtin.c | 9 +-- validation/expand/builtin-expect.c | 101 +++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 validation/expand/builtin-expect.c diff --git a/builtin.c b/builtin.c index 2cafcbda1..7f9ff3582 100644 --- a/builtin.c +++ b/builtin.c @@ -82,13 +82,6 @@ error: return 0; } -static int evaluate_expect(struct expression *expr) -{ - /* Should we evaluate it to return the type of the first argument? */ - expr->ctype = &int_ctype; - return 1; -} - static int arguments_choose(struct expression *expr) { return eval_args(expr, 3); @@ -198,7 +191,6 @@ static struct symbol_op warning_op = { }; static struct symbol_op expect_op = { - .evaluate = evaluate_expect, .expand = expand_expect }; @@ -354,6 +346,7 @@ void declare_builtins(void) declare_builtin("__builtin_ctzl", &int_ctype, 0, &long_ctype, NULL); declare_builtin("__builtin_ctzll", &int_ctype, 0, &llong_ctype, NULL); declare_builtin("__builtin_exit", &void_ctype, 0, &int_ctype, NULL); + declare_builtin("__builtin_expect", &long_ctype, 0, &long_ctype ,&long_ctype, NULL); declare_builtin("__builtin_extract_return_addr", &ptr_ctype, 0, &ptr_ctype, NULL); declare_builtin("__builtin_fabs", &double_ctype, 0, &double_ctype, NULL); declare_builtin("__builtin_ffs", &int_ctype, 0, &int_ctype, NULL); diff --git a/validation/expand/builtin-expect.c b/validation/expand/builtin-expect.c new file mode 100644 index 000000000..a80176a50 --- /dev/null +++ b/validation/expand/builtin-expect.c @@ -0,0 +1,101 @@ +int flia(long a) +{ + return __builtin_expect(a, 1); +} + +int flic(void) +{ + return __builtin_expect(1L << 32 | 1, 1); +} + +long fila(int a) +{ + return __builtin_expect(a, 1); +} + +long filc(void) +{ + return __builtin_expect(1L << 32 | 1, 1); +} + +long filu(void) +{ + return __builtin_expect(0x80000000U, 1); +} + +long fils(void) +{ + return __builtin_expect((int)0x80000000, 1); +} + +void *fptr(void *a) +{ + return __builtin_expect(a, a); +} + +/* + * check-name: builtin-expect + * check-command: test-linearize -m64 -Wno-decl $file + * + * check-output-start +flia: +.L0: + <entry-point> + scast.32 %r2 <- (64) %arg1 + ret.32 %r2 + + +flic: +.L2: + <entry-point> + ret.32 $1 + + +fila: +.L4: + <entry-point> + scast.64 %r6 <- (32) %arg1 + ret.64 %r6 + + +filc: +.L6: + <entry-point> + ret.64 $0x100000001 + + +filu: +.L8: + <entry-point> + ret.64 $0x80000000 + + +fils: +.L10: + <entry-point> + ret.64 $0xffffffff80000000 + + +fptr: +.L12: + <entry-point> + cast.64 %r12 <- (64) %arg1 + scast.64 %r13 <- (64) %r12 + ret.64 %r13 + + + * check-output-end + * + * check-error-start +expand/builtin-expect.c:33:33: warning: incorrect type in argument 1 (different base types) +expand/builtin-expect.c:33:33: expected long [signed] <noident> +expand/builtin-expect.c:33:33: got void *a +expand/builtin-expect.c:33:36: warning: incorrect type in argument 2 (different base types) +expand/builtin-expect.c:33:36: expected long [signed] <noident> +expand/builtin-expect.c:33:36: got void *a +expand/builtin-expect.c:33:32: warning: incorrect type in return expression (different base types) +expand/builtin-expect.c:33:32: expected void * +expand/builtin-expect.c:33:32: got long +expand/builtin-expect.c:8:42: warning: cast truncates bits from constant value (100000001 becomes 1) + * check-error-end + */ -- 2.17.1 -- To unsubscribe from this list: send the line "unsubscribe linux-sparse" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html