These builtins should accept a single argument of any floating-point type and should not do the usual promotion of float to double. Add the type and argument number check in the builtin's evaluate method. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- builtin.c | 30 ++++++++++++++ validation/builtin-fp-unop.c | 95 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 validation/builtin-fp-unop.c diff --git a/builtin.c b/builtin.c index 9aa109d15..dc5f4a68f 100644 --- a/builtin.c +++ b/builtin.c @@ -237,6 +237,27 @@ static struct symbol_op bswap_op = { }; +static int evaluate_fp_unop(struct expression *expr) +{ + struct expression *arg; + + if (!eval_args(expr, 1)) + return 0; + + arg = first_expression(expr->args); + if (!is_float_type(arg->ctype)) { + expression_error(expr, "non-floating-point argument in call to %s()", + show_ident(expr->fn->ctype->ident)); + return 0; + } + return 1; +} + +static struct symbol_op fp_unop_op = { + .evaluate = evaluate_fp_unop, +}; + + /* * Builtin functions */ @@ -255,6 +276,12 @@ static struct sym_init { { "__builtin_bswap16", &builtin_fn_type, MOD_TOPLEVEL, &bswap_op }, { "__builtin_bswap32", &builtin_fn_type, MOD_TOPLEVEL, &bswap_op }, { "__builtin_bswap64", &builtin_fn_type, MOD_TOPLEVEL, &bswap_op }, + { "__builtin_isfinite", &builtin_fn_type, MOD_TOPLEVEL, &fp_unop_op }, + { "__builtin_isinf", &builtin_fn_type, MOD_TOPLEVEL, &fp_unop_op }, + { "__builtin_isinf_sign", &builtin_fn_type, MOD_TOPLEVEL, &fp_unop_op }, + { "__builtin_isnan", &builtin_fn_type, MOD_TOPLEVEL, &fp_unop_op }, + { "__builtin_isnormal", &builtin_fn_type, MOD_TOPLEVEL, &fp_unop_op }, + { "__builtin_signbit", &builtin_fn_type, MOD_TOPLEVEL, &fp_unop_op }, { NULL, NULL, 0 } }; @@ -343,11 +370,13 @@ void declare_builtins(void) declare_builtin("__builtin_isfinite", &int_ctype, 1, NULL); declare_builtin("__builtin_isgreater", &int_ctype, 0, &float_ctype, &float_ctype, NULL); declare_builtin("__builtin_isgreaterequal", &int_ctype, 0, &float_ctype, &float_ctype, NULL); + declare_builtin("__builtin_isinf", &int_ctype, 1, NULL); declare_builtin("__builtin_isinf_sign", &int_ctype, 1, NULL); declare_builtin("__builtin_isless", &int_ctype, 0, &float_ctype, &float_ctype, NULL); declare_builtin("__builtin_islessequal", &int_ctype, 0, &float_ctype, &float_ctype, NULL); declare_builtin("__builtin_islessgreater", &int_ctype, 0, &float_ctype, &float_ctype, NULL); declare_builtin("__builtin_isnan", &int_ctype, 1, NULL); + declare_builtin("__builtin_isnormal", &int_ctype, 1, NULL); declare_builtin("__builtin_isunordered", &int_ctype, 0, &float_ctype, &float_ctype, NULL); declare_builtin("__builtin_labs", &long_ctype, 0, &long_ctype, NULL); declare_builtin("__builtin_llabs", &llong_ctype, 0, &llong_ctype, NULL); @@ -374,6 +403,7 @@ void declare_builtins(void) declare_builtin("__builtin_realloc", &ptr_ctype, 0, &ptr_ctype, size_t_ctype, NULL); declare_builtin("__builtin_return_address", &ptr_ctype, 0, &uint_ctype, NULL); declare_builtin("__builtin_rindex", &string_ctype, 0, &const_string_ctype, &int_ctype, NULL); + declare_builtin("__builtin_signbit", &int_ctype, 1, NULL); declare_builtin("__builtin_snprintf", &int_ctype, 1, &string_ctype, size_t_ctype, &const_string_ctype, NULL); declare_builtin("__builtin_sprintf", &int_ctype, 1, &string_ctype, &const_string_ctype, NULL); declare_builtin("__builtin_stpcpy", &string_ctype, 0, &const_string_ctype, &const_string_ctype, NULL); diff --git a/validation/builtin-fp-unop.c b/validation/builtin-fp-unop.c new file mode 100644 index 000000000..f42c587b7 --- /dev/null +++ b/validation/builtin-fp-unop.c @@ -0,0 +1,95 @@ +static void test_not_enough_args(void) +{ + __builtin_isfinite(); + __builtin_isinf(); + __builtin_isinf_sign(); + __builtin_isnan(); + __builtin_isnormal(); + __builtin_signbit(); +} + +static void test_too_many_args(double v) +{ + __builtin_isfinite(v, v); + __builtin_isinf(v, v); + __builtin_isinf_sign(v, v); + __builtin_isnan(v, v); + __builtin_isnormal(v, v); + __builtin_signbit(v, v); +} + +static void test_non_float(int v) +{ + __builtin_isfinite(v); + __builtin_isinf(v); + __builtin_isinf_sign(v); + __builtin_isnan(v); + __builtin_isnormal(v); + __builtin_signbit(v); +} + +static void test_float(float v) +{ + __builtin_isfinite(v); + __builtin_isinf(v); + __builtin_isinf_sign(v); + __builtin_isnan(v); + __builtin_isnormal(v); + __builtin_signbit(v); +} + +static void test_double(double v) +{ + __builtin_isfinite(v); + __builtin_isinf(v); + __builtin_isinf_sign(v); + __builtin_isnan(v); + __builtin_isnormal(v); + __builtin_signbit(v); +} + +static void test_ldouble(long double v) +{ + __builtin_isfinite(v); + __builtin_isinf(v); + __builtin_isinf_sign(v); + __builtin_isnan(v); + __builtin_isnormal(v); + __builtin_signbit(v); +} + +static void test_constant(void) +{ + __builtin_isfinite(0.0); + __builtin_isinf(0.0); + __builtin_isinf_sign(0.0); + __builtin_isnan(0.0); + __builtin_isnormal(0.0); + __builtin_signbit(0.0); +} + +/* + * check-name: builtin float-point unop + * check-command: sparse -Wno-decl $file + * + * check-error-start +builtin-fp-unop.c:3:27: error: not enough arguments for __builtin_isfinite +builtin-fp-unop.c:4:24: error: not enough arguments for __builtin_isinf +builtin-fp-unop.c:5:29: error: not enough arguments for __builtin_isinf_sign +builtin-fp-unop.c:6:24: error: not enough arguments for __builtin_isnan +builtin-fp-unop.c:7:27: error: not enough arguments for __builtin_isnormal +builtin-fp-unop.c:8:26: error: not enough arguments for __builtin_signbit +builtin-fp-unop.c:13:27: error: too many arguments for __builtin_isfinite +builtin-fp-unop.c:14:24: error: too many arguments for __builtin_isinf +builtin-fp-unop.c:15:29: error: too many arguments for __builtin_isinf_sign +builtin-fp-unop.c:16:24: error: too many arguments for __builtin_isnan +builtin-fp-unop.c:17:27: error: too many arguments for __builtin_isnormal +builtin-fp-unop.c:18:26: error: too many arguments for __builtin_signbit +builtin-fp-unop.c:23:27: error: non-floating-point argument in call to __builtin_isfinite() +builtin-fp-unop.c:24:24: error: non-floating-point argument in call to __builtin_isinf() +builtin-fp-unop.c:25:29: error: non-floating-point argument in call to __builtin_isinf_sign() +builtin-fp-unop.c:26:24: error: non-floating-point argument in call to __builtin_isnan() +builtin-fp-unop.c:27:27: error: non-floating-point argument in call to __builtin_isnormal() +builtin-fp-unop.c:28:26: error: non-floating-point argument in call to __builtin_signbit() + * check-error-end + */ -- 2.16.0 -- 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