This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR43045


This fixes type-verification ICEs with mixed-language LTO (C + Fortran)
related to function call return types.  We already possibly insert
conversions during inlining but happen to not use the type of the
LHS of the call expression when available but that of the function
type return type.

This leads to problems with Fortran and ISO C bindings of at least
function pointers.

Fixed with the following patch.  Bootstrapped and tested on 
x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2010-02-22  Richard Guenther  <rguenther@suse.de>

	PR lto/43045
	* tree-inline.c (declare_return_variable): Use the type of
	the call stmt lhs if available.

	* gfortran.dg/lto/20100222-1_0.f03: New testcase.
	* gfortran.dg/lto/20100222-1_1.c: Likewise.

Index: gcc/tree-inline.c
===================================================================
*** gcc/tree-inline.c	(revision 156949)
--- gcc/tree-inline.c	(working copy)
*************** declare_return_variable (copy_body_data
*** 2542,2550 ****
    tree caller = id->dst_fn;
    tree result = DECL_RESULT (callee);
    tree callee_type = TREE_TYPE (result);
!   tree caller_type = TREE_TYPE (TREE_TYPE (callee));
    tree var, use;
  
    /* We don't need to do anything for functions that don't return
       anything.  */
    if (!result || VOID_TYPE_P (callee_type))
--- 2542,2557 ----
    tree caller = id->dst_fn;
    tree result = DECL_RESULT (callee);
    tree callee_type = TREE_TYPE (result);
!   tree caller_type;
    tree var, use;
  
+   /* Handle type-mismatches in the function declaration return type
+      vs. the call expression.  */
+   if (modify_dest)
+     caller_type = TREE_TYPE (modify_dest);
+   else
+     caller_type = TREE_TYPE (TREE_TYPE (callee));
+ 
    /* We don't need to do anything for functions that don't return
       anything.  */
    if (!result || VOID_TYPE_P (callee_type))
Index: gcc/testsuite/gfortran.dg/lto/20100222-1_0.f03
===================================================================
--- gcc/testsuite/gfortran.dg/lto/20100222-1_0.f03	(revision 0)
+++ gcc/testsuite/gfortran.dg/lto/20100222-1_0.f03	(revision 0)
@@ -0,0 +1,35 @@
+! { dg-lto-do run }
+! This testcase tests c_funloc and c_funptr from iso_c_binding.  It uses 
+! functions defined in c_funloc_tests_3_funcs.c.
+module c_funloc_tests_3
+ implicit none
+contains
+  function ffunc(j) bind(c)
+    use iso_c_binding, only: c_funptr, c_int
+    integer(c_int)        :: ffunc
+    integer(c_int), value :: j
+    ffunc = -17*j
+  end function ffunc
+end module c_funloc_tests_3
+program main
+  use iso_c_binding, only: c_funptr, c_funloc
+  use c_funloc_tests_3, only: ffunc
+  implicit none
+  interface
+    function returnFunc() bind(c,name="returnFunc")
+       use iso_c_binding, only: c_funptr
+       type(c_funptr) :: returnFunc
+    end function returnFunc
+    subroutine callFunc(func,pass,compare) bind(c,name="callFunc")
+       use iso_c_binding, only: c_funptr, c_int
+       type(c_funptr), value :: func
+       integer(c_int), value :: pass,compare
+    end subroutine callFunc
+  end interface
+  type(c_funptr) :: p
+  p = returnFunc()
+  call callFunc(p, 13,3*13)
+  p = c_funloc(ffunc)
+  call callFunc(p, 21,-17*21)
+end program main
+! { dg-final { cleanup-modules "c_funloc_tests_3" } }
Index: gcc/testsuite/gfortran.dg/lto/20100222-1_1.c
===================================================================
--- gcc/testsuite/gfortran.dg/lto/20100222-1_1.c	(revision 0)
+++ gcc/testsuite/gfortran.dg/lto/20100222-1_1.c	(revision 0)
@@ -0,0 +1,25 @@
+/* These functions support the test case c_funloc_tests_3.  */
+#include <stdlib.h>
+#include <stdio.h>
+
+int printIntC(int i)
+{
+  return 3*i;
+}
+
+int (*returnFunc(void))(int)
+{
+  return &printIntC;
+}
+
+void callFunc(int(*func)(int), int pass, int compare)
+{
+  int result = (*func)(pass);
+  if(result != compare)
+    {
+       printf("FAILED: Got %d, expected %d\n", result, compare);
+       abort();
+    }
+  else
+    printf("SUCCESS: Got %d, expected %d\n", result, compare);
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]