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

Reply via email to