https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77278
--- Comment #30 from Jan Hubicka <hubicka at ucw dot cz> --- Hi, this patch makes Fortran logicals to become C unsigned types of corresponding size. I think it is better than making them signed because the globbing will affect aliasing within Fortran programs as well. We still ignore sign on chars and size_t, so this is still throwing away some precision (i.e. LOGICAL of size 1 will become INTEGER if size 1 for TBAA purposes) Index: lto/lto-common.c =================================================================== --- lto/lto-common.c (revision 272506) +++ lto/lto-common.c (working copy) @@ -238,6 +238,8 @@ hash_canonical_type (tree type) types. */ gcc_checking_assert (type_with_alias_set_p (type)); + type = type_for_canonical_type_merging (type); + /* Combine a few common features of types so that types are grouped into smaller sets; when searching for existing matching types to merge, only existing types having the same features as the new type will be Index: testsuite/gfortran.dg/lto/bind_c-7_0.f90 =================================================================== --- testsuite/gfortran.dg/lto/bind_c-7_0.f90 (nonexistent) +++ testsuite/gfortran.dg/lto/bind_c-7_0.f90 (working copy) @@ -0,0 +1,33 @@ +! { dg-lto-do run } +! { dg-lto-options {{ -O3 -flto }} } +! this testcase tests additional interoperability of Fortran logical +! that is not part of the standard but needed by libgfortran. +program main + logical (kind=1) :: l1 + logical (kind=2) :: l2 + logical (kind=4) :: l4 + logical (kind=8) :: l8 + logical (kind=16) :: l16 + + l1 = .true. + l2 = .true. + l4 = .true. + l8 = .true. + call logical_c (l1, l2, l4, l8, l16) + if (l1 .or. l2 .or. l4 .or. l8 .or. l16) stop 1 +end program main + +subroutine foo(l1, l2, l4, l8, l16) + logical (kind=1) :: l1 + logical (kind=2) :: l2 + logical (kind=4) :: l4 + logical (kind=8) :: l8 + logical (kind=16) :: l16 + + l1 = .false. + l2 = .false. + l4 = .false. + l8 = .false. + l16 = .false. +end subroutine foo + Index: testsuite/gfortran.dg/lto/bind_c-7_1.c =================================================================== --- testsuite/gfortran.dg/lto/bind_c-7_1.c (nonexistent) +++ testsuite/gfortran.dg/lto/bind_c-7_1.c (working copy) @@ -0,0 +1,6 @@ + +extern void foo_ (_Bool *l1, unsigned short *l2, unsigned int *l4, unsigned long long *l8, unsigned __int128 *l16); +void logical_c_ (_Bool *l1, unsigned short *l2, unsigned int *l4, unsigned long long *l8, unsigned __int128 *l16) +{ + foo_ (l1, l2, l4, l8, l16); +} Index: tree.c =================================================================== --- tree.c (revision 272506) +++ tree.c (working copy) @@ -14047,6 +14053,25 @@ type_with_interoperable_signedness (cons || TYPE_PRECISION (type) == TYPE_PRECISION (size_type_node)); } +/* Return type replacing TYPE for canonical type merging. + + We translate BOOLEAN_TYPE of size different from C _Bool to + unsigned integers. This makes it possible to interoperate C + and Fortran on Fortran's LOGICAL types which come in different + sizes. This is not required by the language standard but + used by libgfortran. */ + +extern tree +type_for_canonical_type_merging (const_tree type) +{ + if (TREE_CODE (type) == BOOLEAN_TYPE + && !tree_int_cst_equal (TYPE_SIZE (type), + TYPE_SIZE (boolean_type_node))) + return lang_hooks.types.type_for_mode (TYPE_MODE (type), + true); + return const_cast <tree> (type); +} + /* Return true iff T1 and T2 are structurally identical for what TBAA is concerned. This function is used both by lto.c canonical type merging and by the @@ -14066,6 +14091,8 @@ gimple_canonical_types_compatible_p (con t1 = TYPE_MAIN_VARIANT (t1); t2 = TYPE_MAIN_VARIANT (t2); } + t1 = type_for_canonical_type_merging (t1); + t2 = type_for_canonical_type_merging (t2); /* Check first for the obvious case of pointer identity. */ if (t1 == t2) Index: tree.h =================================================================== --- tree.h (revision 272506) +++ tree.h (working copy) @@ -5132,9 +5141,10 @@ extern void DEBUG_FUNCTION verify_type ( extern bool gimple_canonical_types_compatible_p (const_tree, const_tree, bool trust_type_canonical = true); extern bool type_with_interoperable_signedness (const_tree); +extern tree type_for_canonical_type_merging (const_tree type); extern bitmap get_nonnull_args (const_tree); extern int get_range_pos_neg (tree); /* Return simplified tree code of type that is used for canonical type merging. */ inline enum tree_code