:ADDPATCH testsuite:
Attached patch fixes a bug (PR libfortran/22298) where the libgfortran
constructor function wasn't linked in when libgfortran was statically
linked. The patch itself is straightforward and well commented, and it
could go under the "obvious rule".
I added a test for the testsuite, conditionnal on a new effective
target. Could someone OK this part?
Thanks,
FX
2005-10-30 Francois-Xavier Coudert <[EMAIL PROTECTED]>
PR libfortran/22298
* runtime/main.c (stupid_function_name_for_static_linking): New
function.
* runtime/error.c (internal_error): Call
stupid_function_name_for_static_linking.
* libgfortran.h: Add prototype for
stupid_function_name_for_static_linking.
2005-10-30 Francois-Xavier Coudert <[EMAIL PROTECTED]>
PR libfortran/22298
* gcc/testsuite/lib/target-supports.exp
(check_effective_target_static_libgfortran): New
static_libgfortran effective target.
* gcc/testsuite/gfortran.dg/static_linking_1.f: New test.
* gcc/testsuite/gfortran.dg/static_linking_1.c: New file.
Index: libgfortran/runtime/main.c
===================================================================
--- libgfortran/runtime/main.c (revision 105991)
+++ libgfortran/runtime/main.c (working copy)
@@ -35,6 +35,14 @@
#include "libgfortran.h"
+/* Stupid function to be sure the constructor is always linked in, even
+ in the case of static linking. See PR libfortran/22298 for details. */
+void
+stupid_function_name_for_static_linking (void)
+{
+ return;
+}
+
/* This is the offset (in bytes) required to cast from logical(8)* to
logical(4)*. and still get the same result. Will be 0 for little-endian
machines and 4 for big-endian machines. */
Index: libgfortran/runtime/error.c
===================================================================
--- libgfortran/runtime/error.c (revision 105991)
+++ libgfortran/runtime/error.c (working copy)
@@ -353,6 +353,13 @@
recursion_check ();
show_locus ();
st_printf ("Internal Error: %s\n", message);
+
+ /* This function call is here to get the main.o object file included
+ when linking statically. This works because error.o is supposed to
+ be always linked in (and the function call is in internal_error
+ because hopefully it doesn't happen too often). */
+ stupid_function_name_for_static_linking();
+
sys_exit (3);
}
Index: libgfortran/libgfortran.h
===================================================================
--- libgfortran/libgfortran.h (revision 105991)
+++ libgfortran/libgfortran.h (working copy)
@@ -434,6 +434,9 @@
/* main.c */
+extern void stupid_function_name_for_static_linking (void);
+internal_proto(stupid_function_name_for_static_linking);
+
extern void library_start (void);
internal_proto(library_start);
Index: gcc/testsuite/lib/target-supports.exp
===================================================================
--- gcc/testsuite/lib/target-supports.exp (revision 105991)
+++ gcc/testsuite/lib/target-supports.exp (working copy)
@@ -522,6 +522,59 @@
return $et_fortran_large_int_saved
}
+# Return 1 if we can statically link libgfortran, 0 otherwise.
+#
+# When the target name changes, replace the cached result.
+
+proc check_effective_target_static_libgfortran { } {
+ global et_static_libgfortran
+ global et_static_libgfortran_target_name
+ global tool
+
+ if { ![info exists et_static_libgfortran_target_name] } {
+ set et_static_libgfortran_target_name ""
+ }
+
+ # If the target has changed since we set the cached value, clear it.
+ set current_target [current_target_name]
+ if { $current_target != $et_static_libgfortran_target_name } {
+ verbose "check_effective_target_static_libgfortran: `$et_static_libgfortran_target_name' `$current_target'" 2
+ set et_static_libgfortran_target_name $current_target
+ if [info exists et_static_libgfortran_saved] {
+ verbose "check_effective_target_static_libgfortran: removing cached result" 2
+ unset et_static_libgfortran_saved
+ }
+ }
+
+ if [info exists et_static_libgfortran_saved] {
+ verbose "check_effective_target_static_libgfortran returning saved $et_static_libgfortran_saved" 2
+ } else {
+ set et_static_libgfortran_saved 0
+
+ # Set up, compile, and execute a test program using large integer
+ # kinds. Include the current process ID in the file names to
+ # prevent conflicts with invocations for multiple testsuites.
+ set src static[pid].f
+ set exe static[pid].x
+
+ set f [open $src "w"]
+ puts $f " print *, 'test'"
+ puts $f " end"
+ close $f
+
+ verbose "check_effective_target_static_libgfortran compiling testfile $src" 2
+ set lines [${tool}_target_compile $src $exe executable ""]
+ file delete $src
+
+ if [string match "" $lines] then {
+ # No error message, compilation succeeded.
+ set et_static_libgfortran_saved 1
+ }
+ }
+
+ return $et_static_libgfortran_saved
+}
+
# Return 1 if the target supports executing AltiVec instructions, 0
# otherwise. Cache the result.
Index: gcc/testsuite/gfortran.dg/static_linking_1.c
===================================================================
--- gcc/testsuite/gfortran.dg/static_linking_1.c (revision 0)
+++ gcc/testsuite/gfortran.dg/static_linking_1.c (revision 0)
@@ -0,0 +1,6 @@
+extern void f_(void);
+int main (void)
+{
+ f_();
+ return 0;
+}
Index: gcc/testsuite/gfortran.dg/static_linking_1.f
===================================================================
--- gcc/testsuite/gfortran.dg/static_linking_1.f (revision 0)
+++ gcc/testsuite/gfortran.dg/static_linking_1.f (revision 0)
@@ -0,0 +1,11 @@
+! { dg-require-effective-target static_libgfortran }
+! { dg-do run }
+! { dg-additional-sources static_linking_1.c }
+! { dg-options "-static" }
+!
+! This testcase checks that statically linking libgfortran with C main()
+! really calls the constructor function
+! PR libfortran/22298
+ subroutine f
+ print *, "subroutine output"
+ end