+
+ *handled = false;
+ return false;
+ }
+}
+
+/* Return true if operation OP may trap. FP_OPERATION is true if OP is applied
+ on floating-point values. HONOR_TRAPV is true if OP is applied on integer
+ type operands that may trap. If OP is a division operator, DIVISOR contains
+ the value of the divisor. */
+
+bool
+operation_could_trap_p (enum tree_code op, bool fp_operation, bool honor_trapv,
+ tree divisor)
+{
+ bool honor_nans = (fp_operation && flag_trapping_math
+ && !flag_finite_math_only);
+ bool honor_snans = fp_operation && flag_signaling_nans != 0;
+ bool handled;
+
+ if (TREE_CODE_CLASS (op) != tcc_comparison
+ && TREE_CODE_CLASS (op) != tcc_unary
+ && TREE_CODE_CLASS (op) != tcc_binary)
+ return false;
+
+ return operation_could_trap_helper_p (op, fp_operation, honor_trapv,
+ honor_nans, honor_snans, divisor,
+ &handled);
+}
+
+/* Return true if EXPR can trap, as in dereferencing an invalid pointer
+ location or floating point arithmetic. C.f. the rtl version, may_trap_p.
+ This routine expects only GIMPLE lhs or rhs input. */
+
+bool
+tree_could_trap_p (tree expr)
+{
+ enum tree_code code;
+ bool fp_operation = false;
+ bool honor_trapv = false;
+ tree t, base, div = NULL_TREE;
+
+ if (!expr)
+ return false;
+
+ code = TREE_CODE (expr);
+ t = TREE_TYPE (expr);
+
+ if (t)
+ {
+ if (COMPARISON_CLASS_P (expr))
+ fp_operation = FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)));
+ else
+ fp_operation = FLOAT_TYPE_P (t);
+ honor_trapv = INTEGRAL_TYPE_P (t) && TYPE_OVERFLOW_TRAPS (t);
+ }
+
+ if (TREE_CODE_CLASS (code) == tcc_binary)
+ div = TREE_OPERAND (expr, 1);
+ if (operation_could_trap_p (code, fp_operation, honor_trapv, div))
+ return true;
+
+ restart:
+ switch (code)
+ {
+ case TARGET_MEM_REF:
+ /* For TARGET_MEM_REFs use the information based on the original
+ reference. */
+ expr = TMR_ORIGINAL (expr);
+ code = TREE_CODE (expr);
+ goto restart;
+
+ case COMPONENT_REF:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ case BIT_FIELD_REF:
+ case VIEW_CONVERT_EXPR:
+ case WITH_SIZE_EXPR:
+ expr = TREE_OPERAND (expr, 0);
+ code = TREE_CODE (expr);
+ goto restart;
+
+ case ARRAY_RANGE_REF:
+ base = TREE_OPERAND (expr, 0);
+ if (tree_could_trap_p (base))
+ return true;
+
+ if (TREE_THIS_NOTRAP (expr))
+ return false;
+
+ return !range_in_array_bounds_p (expr);
+
+ case ARRAY_REF:
+ base = TREE_OPERAND (expr, 0);
+ if (tree_could_trap_p (base))
+ return true;
+
+ if (TREE_THIS_NOTRAP (expr))
+ return false;
+
+ return !in_array_bounds_p (expr);
+
+ case INDIRECT_REF:
+ case ALIGN_INDIRECT_REF:
+ case MISALIGNED_INDIRECT_REF:
+ return !TREE_THIS_NOTRAP (expr);
+
+ case ASM_EXPR:
+ return TREE_THIS_VOLATILE (expr);
+
+
+ case CALL_EXPR:
+ t = get_callee_fndecl (expr);
+ /* Assume that calls to weak functions may trap. */
+ if (!t || !DECL_P (t) || DECL_WEAK (t))
+ return true;
+ return false;
+
+ default: