https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120837
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Component|middle-end |c CC| |jsm28 at gcc dot gnu.org --- Comment #12 from Jakub Jelinek <jakub at gcc dot gnu.org> --- So, c-typeck.cc (build_binary_op) is called on x > y ? (void **)&b : (void **)&a as orig_op0 and y - 1 as orig_op1, code PLUS_EXPR. That calls pointer_int_sum with the same operands. But then c-common.cc (pointer_int_sum)'s /* If what we are about to multiply by the size of the elements contains a constant term, apply distributive law and multiply that constant term separately. This helps produce common subexpressions. */ if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR) && !TREE_CONSTANT (intop) && TREE_CONSTANT (TREE_OPERAND (intop, 1)) && TREE_CONSTANT (size_exp) /* If the constant comes from pointer subtraction, skip this optimization--it would cause an error. */ && TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) == INTEGER_TYPE /* If the constant is unsigned, and smaller than the pointer size, then we must skip this optimization. This is because it could cause an overflow error if the constant is negative but INTOP is not. */ && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (intop)) || (TYPE_PRECISION (TREE_TYPE (intop)) == TYPE_PRECISION (TREE_TYPE (ptrop))))) { enum tree_code subcode = resultcode; tree int_type = TREE_TYPE (intop); if (TREE_CODE (intop) == MINUS_EXPR) subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR); /* Convert both subexpression types to the type of intop, because weird cases involving pointer arithmetic can result in a sum or difference with different type args. */ ptrop = build_binary_op (EXPR_LOCATION (TREE_OPERAND (intop, 1)), subcode, ptrop, convert (int_type, TREE_OPERAND (intop, 1)), true); intop = convert (int_type, TREE_OPERAND (intop, 0)); } That looks just wrong generally, there is no attempt to prove that ptrop - 1 is not invalid, this is sort of optimization I'd expect to be done in ivopts or so and use uintptr_t arithmetics instead of pointer arithmetics. This is 1992-ish code with some later extensions. Dunno if the best thing is to just drop this altogether, or don't do it for -fsanitize=undefined, or do it but on pointer sized ints instead of pointers.