On Fri, Nov 10, 2017 at 3:54 PM, Andrew MacLeod <amacl...@redhat.com> wrote: > On 11/10/2017 09:03 AM, Richard Biener wrote: >> >> On Fri, Nov 10, 2017 at 2:49 PM, Andrew MacLeod <amacl...@redhat.com> >> wrote: >>> >>> Before I open a PR, I want to confirm my beliefs. >>> >>> >>> Is it not true that both operations of a gimple operation such as == or >>> != >>> must satisfy types_compatible_p (op1_type, op2_type) ? Even when one is >>> a >>> constant? >>> >>> given : >>> >>> _10 = _2 != 0 >>> >>> so the generic node for the 0 needs to be a type compatible with _2? >>> >>> I ask because I tripped over a fortran test where that is not true. It is >>> comparing a function pointer of some sort with a (void *)0, and the >>> types_compatible_p check fails. >>> >>> I hacked the compiler to check when building a gimple assign to verify >>> that >>> the types are compatible. It succeeds and entire bootstrap cycle, which >>> leads me to believe my assertion is true. For some reason I thought there >>> was gimple verification that would catch things like this.. apparently >>> not? >>> >>> Index: gimple.c >>> =================================================================== >>> *** gimple.c (revision 254327) >>> --- gimple.c (working copy) >>> *************** gimple_build_assign_1 (tree lhs, enum tr >>> *** 423,428 **** >>> --- 423,430 ---- >>> { >>> gcc_assert (num_ops > 2); >>> gimple_assign_set_rhs2 (p, op2); >>> + if (subcode == EQ_EXPR || subcode == NE_EXPR) >>> + gcc_assert (types_compatible_p (TREE_TYPE (op1), TREE_TYPE (op2))); >>> } >>> >>> >>> and when I run it on this small program: >>> >>> interface >>> integer function foo () >>> end function >>> integer function baz () >>> end function >>> end interface >>> procedure(foo), pointer :: ptr >>> ptr => baz >>> if (.not.associated (ptr, baz)) call abort >>> end >>> >>> I get a trap on this statement: >>> >>> if (.not.associated (ptr, baz)) call abort >>> >>> internal compiler error: in gimple_build_assign_1, at gimple.c:443 >>> >>> The IL is comparing >>> ptr == 0B >>> >>> and I see: >>> Type op1 : 0x7fd8e312df18 -> integer(kind=4) (*<T561>) (void) >>> Type op2 : 0x7fd8e2fa10a8 -> void * >>> >>> These 2 types fail the types_compatible_p test. >>> >>> So is this a bug like I think it is? >> >> Always look at tree-cfg.c:verify_gimple_* >> >> Quoting: >> >> static bool >> verify_gimple_comparison (tree type, tree op0, tree op1, enum tree_code >> code) >> { >> ... >> /* For comparisons we do not have the operations type as the >> effective type the comparison is carried out in. Instead >> we require that either the first operand is trivially >> convertible into the second, or the other way around. >> Because we special-case pointers to void we allow >> comparisons of pointers with the same mode as well. */ >> if (!useless_type_conversion_p (op0_type, op1_type) >> && !useless_type_conversion_p (op1_type, op0_type) >> && (!POINTER_TYPE_P (op0_type) >> || !POINTER_TYPE_P (op1_type) >> || TYPE_MODE (op0_type) != TYPE_MODE (op1_type))) >> { >> error ("mismatching comparison operand types"); >> debug_generic_expr (op0_type); >> debug_generic_expr (op1_type); >> return true; >> } >> >> this is exactly because we have that "wart" >> >> bool >> useless_type_conversion_p (tree outer_type, tree inner_type) >> { >> /* Do the following before stripping toplevel qualifiers. */ >> if (POINTER_TYPE_P (inner_type) >> && POINTER_TYPE_P (outer_type)) >> { >> ... >> /* Do not lose casts to function pointer types. */ >> if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE >> || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE) >> && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE >> || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE)) >> return false; >> } >> >> which is IIRC because of targets with function descriptors (details are >> lost >> on me, but I remember repeatedly trying to get rid of this special case). >> > Huh, that bites. Im surprised we don't just make those places produce a > cast, or just introduce an explicit cast of the (void *)0 during the > expression building process.
I'm quite sure we could relax the above now given we have gimple_call_fntype to preserve the original function type. But I don't remember what broke and exactly why on those pesky fn descriptor targets. These days I only know about IA64. Richard. > Of course, I'm sure its not that simple :-P Nothing ever is. > > OKeydoke. I'll leave it as is an allow the wart to pass my code as well for > the moment. > > Thanks > Adnrew > >