@@ -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,
@@ -10995,7 +10995,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))
@@ -11006,7 +11007,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);
@@ -4112,10 +4112,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)
@@ -4155,9 +4152,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);
}
@@ -4904,7 +4899,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",
@@ -4918,7 +4914,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
@@ -228,9 +228,11 @@ 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
+ | SANITIZE_FLOAT_DIVIDE
};
/* flag_vtable_verify initialization levels. */
@@ -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;
@@ -1,4 +1,4 @@
-/* { dg-do compile} */
+/* { dg-do compile } */
/* { dg-options "-fsanitize=integer-divide-by-zero" } */
void
@@ -0,0 +1,25 @@
+/* { 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;
+
+ a / b;
+ a / 0.0;
+ 2.7f / b;
+ 3.6 / (b = 0.0, b);
+ c / b;
+ 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]*" } */