diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7b4bb549d8a..1bec6e12fa8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2014-04-30 Marek Polacek + + * gcc.c (sanitize_spec_function): Handle SANITIZE_FLOAT_DIVIDE. + * builtins.def: Initialize builtins even for SANITIZE_FLOAT_DIVIDE. + * flag-types.h (enum sanitize_code): Add SANITIZE_FLOAT_DIVIDE. + * opts.c (common_handle_option): Add -fsanitize=float-divide-by-zero. + 2014-04-29 Alan Lawrence * config/aarch64/arm_neon.h (vzip1_f32, vzip1_p8, vzip1_p16, vzip1_s8, diff --git a/gcc/builtins.def b/gcc/builtins.def index 5b902d8a938..d400ecb4e8f 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -176,7 +176,7 @@ along with GCC; see the file COPYING3. If not see DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \ true, true, true, ATTRS, true, \ (flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_THREAD \ - | SANITIZE_UNDEFINED))) + | SANITIZE_UNDEFINED | SANITIZE_FLOAT_DIVIDE))) #undef DEF_CILKPLUS_BUILTIN #define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS) \ diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index fb0d102eac3..47bb11438ad 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2014-04-30 Marek Polacek + + * c-ubsan.c (ubsan_instrument_division): Handle REAL_TYPEs. Perform + INT_MIN / -1 sanitization only for integer types. + 2014-04-25 Marek Polacek PR c/18079 diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c index e4f6f327277..a0397925fe7 100644 --- a/gcc/c-family/c-ubsan.c +++ b/gcc/c-family/c-ubsan.c @@ -46,15 +46,21 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1) gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (op0)) == TYPE_MAIN_VARIANT (TREE_TYPE (op1))); - /* TODO: REAL_TYPE is not supported yet. */ - if (TREE_CODE (type) != INTEGER_TYPE) + if (TREE_CODE (type) == INTEGER_TYPE + && (flag_sanitize & SANITIZE_DIVIDE)) + t = fold_build2 (EQ_EXPR, boolean_type_node, + op1, build_int_cst (type, 0)); + else if (TREE_CODE (type) == REAL_TYPE + && (flag_sanitize & SANITIZE_FLOAT_DIVIDE)) + t = fold_build2 (EQ_EXPR, boolean_type_node, + op1, build_real (type, dconst0)); + else return NULL_TREE; - t = fold_build2 (EQ_EXPR, boolean_type_node, - op1, build_int_cst (type, 0)); - /* We check INT_MIN / -1 only for signed types. */ - if (!TYPE_UNSIGNED (type)) + if (TREE_CODE (type) == INTEGER_TYPE + && (flag_sanitize & SANITIZE_DIVIDE) + && !TYPE_UNSIGNED (type)) { tree x; tt = fold_build2 (EQ_EXPR, boolean_type_node, op1, diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index d54b62e11ea..bf61610e37c 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,8 @@ +2014-04-30 Marek Polacek + + * c-typeck.c (build_binary_op): Call ubsan_instrument_division + also when SANITIZE_FLOAT_DIVIDE is on. + 2014-04-30 Marek Polacek PR c/60139 diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 6e56b69ab5f..cb8ae44e363 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -10997,7 +10997,8 @@ build_binary_op (location_t location, enum tree_code code, return error_mark_node; } - if ((flag_sanitize & (SANITIZE_SHIFT | SANITIZE_DIVIDE)) + if ((flag_sanitize & (SANITIZE_SHIFT | SANITIZE_DIVIDE + | SANITIZE_FLOAT_DIVIDE)) && current_function_decl != 0 && !lookup_attribute ("no_sanitize_undefined", DECL_ATTRIBUTES (current_function_decl)) @@ -11008,7 +11009,8 @@ build_binary_op (location_t location, enum tree_code code, op1 = c_save_expr (op1); op0 = c_fully_fold (op0, false, NULL); op1 = c_fully_fold (op1, false, NULL); - if (doing_div_or_mod && (flag_sanitize & SANITIZE_DIVIDE)) + if (doing_div_or_mod && (flag_sanitize & (SANITIZE_DIVIDE + | SANITIZE_FLOAT_DIVIDE))) instrument_expr = ubsan_instrument_division (location, op0, op1); else if (doing_shift && (flag_sanitize & SANITIZE_SHIFT)) instrument_expr = ubsan_instrument_shift (location, code, op0, op1); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b2018255b18..c4be5bdde6c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2014-04-30 Marek Polacek + + * typeck.c (cp_build_binary_op): Call ubsan_instrument_division + even when SANITIZE_FLOAT_DIVIDE is on. Set doing_div_or_mod even + for non-integer types. + 2014-04-29 Jason Merrill DR 1351 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index ae7fa776eb8..729e22eadc5 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -4110,10 +4110,7 @@ cp_build_binary_op (location_t location, enum tree_code tcode0 = code0, tcode1 = code1; tree cop1 = fold_non_dependent_expr_sfinae (op1, tf_none); cop1 = maybe_constant_value (cop1); - - if (tcode0 == INTEGER_TYPE) - doing_div_or_mod = true; - + doing_div_or_mod = true; warn_for_div_by_zero (location, cop1); if (tcode0 == COMPLEX_TYPE || tcode0 == VECTOR_TYPE) @@ -4153,9 +4150,7 @@ cp_build_binary_op (location_t location, { tree cop1 = fold_non_dependent_expr_sfinae (op1, tf_none); cop1 = maybe_constant_value (cop1); - - if (code0 == INTEGER_TYPE) - doing_div_or_mod = true; + doing_div_or_mod = true; warn_for_div_by_zero (location, cop1); } @@ -4902,7 +4897,8 @@ cp_build_binary_op (location_t location, if (build_type == NULL_TREE) build_type = result_type; - if ((flag_sanitize & (SANITIZE_SHIFT | SANITIZE_DIVIDE)) + if ((flag_sanitize & (SANITIZE_SHIFT | SANITIZE_DIVIDE + | SANITIZE_FLOAT_DIVIDE)) && !processing_template_decl && current_function_decl != 0 && !lookup_attribute ("no_sanitize_undefined", @@ -4916,7 +4912,8 @@ cp_build_binary_op (location_t location, tf_none)); op1 = maybe_constant_value (fold_non_dependent_expr_sfinae (op1, tf_none)); - if (doing_div_or_mod && (flag_sanitize & SANITIZE_DIVIDE)) + if (doing_div_or_mod && (flag_sanitize & (SANITIZE_DIVIDE + | SANITIZE_FLOAT_DIVIDE))) { /* For diagnostics we want to use the promoted types without shorten_binary_op. So convert the arguments to the diff --git a/gcc/flag-types.h b/gcc/flag-types.h index fc3261bbbb7..caf4039f9df 100644 --- a/gcc/flag-types.h +++ b/gcc/flag-types.h @@ -228,6 +228,7 @@ enum sanitize_code { SANITIZE_SI_OVERFLOW = 1 << 9, SANITIZE_BOOL = 1 << 10, SANITIZE_ENUM = 1 << 11, + SANITIZE_FLOAT_DIVIDE = 1 << 12, SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE | SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN | SANITIZE_SI_OVERFLOW | SANITIZE_BOOL | SANITIZE_ENUM diff --git a/gcc/gcc.c b/gcc/gcc.c index e5130d13535..7bea6d79ac2 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -8170,7 +8170,7 @@ sanitize_spec_function (int argc, const char **argv) if (strcmp (argv[0], "thread") == 0) return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL; if (strcmp (argv[0], "undefined") == 0) - return ((flag_sanitize & SANITIZE_UNDEFINED) + return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_FLOAT_DIVIDE)) && !flag_sanitize_undefined_trap_on_error) ? "" : NULL; if (strcmp (argv[0], "leak") == 0) return ((flag_sanitize diff --git a/gcc/opts.c b/gcc/opts.c index 1873b96a028..3c214f09701 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -1461,6 +1461,8 @@ common_handle_option (struct gcc_options *opts, sizeof "signed-integer-overflow" -1 }, { "bool", SANITIZE_BOOL, sizeof "bool" - 1 }, { "enum", SANITIZE_ENUM, sizeof "enum" - 1 }, + { "float-divide-by-zero", SANITIZE_FLOAT_DIVIDE, + sizeof "float-divide-by-zero" - 1 }, { NULL, 0, 0 } }; const char *comma; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index de105037daf..f07c90a7546 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-04-30 Marek Polacek + + * c-c++-common/ubsan/div-by-zero-5.c: Fix formatting. + * c-c++-common/ubsan/float-div-by-zero-1.c: New test. + 2014-04-30 Marek Polacek PR c/60139 diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c index 7a28bacd14b..bb391c5b36d 100644 --- a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c +++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c @@ -1,4 +1,4 @@ -/* { dg-do compile} */ +/* { dg-do compile } */ /* { dg-options "-fsanitize=integer-divide-by-zero" } */ void diff --git a/gcc/testsuite/c-c++-common/ubsan/float-div-by-zero-1.c b/gcc/testsuite/c-c++-common/ubsan/float-div-by-zero-1.c new file mode 100644 index 00000000000..2271ea9b776 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/float-div-by-zero-1.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=float-divide-by-zero" } */ + +int +main (void) +{ + volatile float a = 1.3f; + volatile double b = 0.0; + volatile int c = 4; + volatile float res; + + res = a / b; + res = a / 0.0; + res = 2.7f / b; + res = 3.6 / (b = 0.0, b); + res = c / b; + res = b / c; + + return 0; +} + +/* { dg-output "division by zero\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*division by zero\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*division by zero\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*division by zero\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*division by zero\[^\n\r]*" } */