[RFC] Implement Undefined Behavior Sanitizer (take 2)
Jakub Jelinek
jakub@redhat.com
Wed Jun 12 15:29:00 GMT 2013
On Wed, Jun 12, 2013 at 05:17:45PM +0200, Marek Polacek wrote:
> @@ -3867,6 +3868,7 @@ cp_build_binary_op (location_t location,
> tree final_type = 0;
>
> tree result;
> + tree orig_type = NULL;
>
> /* Nonzero if this is an operation like MIN or MAX which can
> safely be computed in short if both args are promoted shorts.
> @@ -3891,6 +3893,15 @@ cp_build_binary_op (location_t location,
> op0 = orig_op0;
> op1 = orig_op1;
>
> + /* Remember whether we're doing / or %. */
> + bool doing_div_or_mod = false;
> +
> + /* Remember whether we're doing << or >>. */
> + bool doing_shift = false;
> +
> + /* Tree holding instrumentation expression. */
> + tree instrument_expr = NULL;
> +
> if (code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR
> || code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR
> || code == TRUTH_XOR_EXPR)
> @@ -4070,8 +4081,12 @@ 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);
>
> - warn_for_div_by_zero (location, maybe_constant_value (cop1));
> + if (!processing_template_decl && tcode0 == INTEGER_TYPE)
> + doing_div_or_mod = true;
Either the !processing_template_decl here is unneeded, or
if you'd check it (and perhaps flag_ubsan too) in this part of code,
then you wouldn't need to check it later.
> @@ -4832,6 +4853,31 @@ cp_build_binary_op (location_t location,
> if (build_type == NULL_TREE)
> build_type = result_type;
>
> + if (flag_ubsan && !processing_template_decl)
But, I'd certainly avoid doing the cp_save_expr/maybe_constant_value
etc. for all the binary operations you don't want to instrument
(thus check (doing_div_or_mod || doing_shift) also).
-
> + {
> + /* OP0 and/or OP1 might have side-effects. */
> + op0 = cp_save_expr (op0);
> + op1 = cp_save_expr (op1);
> + op0 = maybe_constant_value (fold_non_dependent_expr_sfinae (op0,
> + tf_none));
> + op1 = maybe_constant_value (fold_non_dependent_expr_sfinae (op1,
> + tf_none));
> + if (doing_div_or_mod)
> + {
> + /* For diagnostics we want to use the promoted types without
> + shorten_binary_op. So convert the arguments to the
> + original result_type. */
> + if (orig_type != NULL && result_type != orig_type)
> + {
> + op0 = cp_convert (orig_type, op0, complain);
> + op1 = cp_convert (orig_type, op1, complain);
And you don't want to change op0/op1, have your own tree vars, assign
op{0,1} to them and change here if result_type is not orig_type,
then pass those vars to ubsan_instrument_division.
Jakub
More information about the Gcc-patches
mailing list