From 9d39b1f00ea895ddbc0b8b99d0de7609645d7dff Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Mon, 6 May 2002 10:29:18 +0000
Subject: [PATCH] Force link-time references despite optimizations done by g++.

---
 ChangeLog                | 24 ++++++++++++++++++++++++
 include/cln/GV_integer.h |  4 +---
 include/cln/GV_number.h  |  4 +---
 include/cln/SV_number.h  |  4 +---
 include/cln/SV_ringelt.h |  4 +---
 include/cln/dfloat.h     |  4 +---
 include/cln/ffloat.h     |  8 ++------
 include/cln/integer.h    |  8 ++------
 include/cln/lfloat.h     |  4 +---
 include/cln/modinteger.h |  4 +---
 include/cln/modules.h    | 22 ++++++++++++++++++++++
 include/cln/rational.h   |  4 +---
 include/cln/real.h       |  4 +---
 include/cln/ring.h       |  4 +---
 include/cln/sfloat.h     |  8 ++------
 include/cln/string.h     |  4 +---
 include/cln/univpoly.h   |  4 +---
 src/float/base/cl_ieee.h |  2 +-
 18 files changed, 65 insertions(+), 55 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 9528338..90fff94 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,29 @@
 2002-05-05  Bruno Haible  <bruno@clisp.org>
 
+	Force link-time references despite optimizations done by g++ 2.95
+	and newer.
+	* include/cln/modules.h (CL_FORCE_LINK): New macro.
+	* Use CL_FORCE_LINK.
+	* include/cln/GV_integer.h (cl_GV_I_debug_dummy): Likewise.
+	* include/cln/GV_number.h (cl_GV_number_debug_dummy): Likewise.
+	* include/cln/SV_number.h (cl_SV_number_debug_dummy): Likewise.
+	* include/cln/SV_ringelt.h (cl_SV_ringelt_debug_dummy): Likewise.
+	* include/cln/dfloat.h (cl_DF_debug_dummy): Likewise.
+	* include/cln/ffloat.h (cl_FF_classes_dummy, cl_FF_debug_dummy):
+	Likewise.
+	* include/cln/integer.h (cl_I_classes_dummy, cl_I_debug_dummy):
+	Likewise.
+	* include/cln/lfloat.h (cl_LF_debug_dummy): Likewise.
+	* include/cln/modinteger.h (cl_MI_debug_dummy): Likewise.
+	* include/cln/rational.h (cl_RA_debug_dummy): Likewise.
+	* include/cln/real.h (cl_R_debug_dummy): Likewise.
+	* include/cln/ring.h (cl_ring_debug_dummy): Likewise.
+	* include/cln/sfloat.h (cl_SF_classes_dummy, cl_SF_classes_dummy):
+	Likewise.
+	* include/cln/string.h (cl_string_debug_dummy): Likewise.
+	* include/cln/univpoly.h (cl_UP_debug_dummy): Likewise.
+	* src/float/base/cl_ieee.h (cl_ieee_dummy_NNN): Likewise.
+
 	Avoid g++ 3.1 warnings.
 	* src/base/cl_offsetof.h (offsetof): Redefine each time.
 	* src/base/digitseq/cl_DS.h: Include "cl_offsetof.h" after <gmp.h>.
diff --git a/include/cln/GV_integer.h b/include/cln/GV_integer.h
index 502ec78..e79d3dd 100644
--- a/include/cln/GV_integer.h
+++ b/include/cln/GV_integer.h
@@ -78,9 +78,7 @@ CL_DEFINE_PRINT_OPERATOR(cl_GV_I)
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_GV_I_debug_module;
-static void* const cl_GV_I_debug_dummy[] = { &cl_GV_I_debug_dummy,
-	&cl_GV_I_debug_module
-};
+CL_FORCE_LINK(cl_GV_I_debug_dummy, cl_GV_I_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/include/cln/GV_number.h b/include/cln/GV_number.h
index a9892fb..14d899d 100644
--- a/include/cln/GV_number.h
+++ b/include/cln/GV_number.h
@@ -40,9 +40,7 @@ extern const cl_GV_number copy (const cl_GV_number&);
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_GV_number_debug_module;
-static void* const cl_GV_number_debug_dummy[] = { &cl_GV_number_debug_dummy,
-	&cl_GV_number_debug_module
-};
+CL_FORCE_LINK(cl_GV_number_debug_dummy, cl_GV_number_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/include/cln/SV_number.h b/include/cln/SV_number.h
index 64db595..810f26c 100644
--- a/include/cln/SV_number.h
+++ b/include/cln/SV_number.h
@@ -52,9 +52,7 @@ inline const cl_SV_number copy (const cl_SV_number& vector)
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_SV_number_debug_module;
-static void* const cl_SV_number_debug_dummy[] = { &cl_SV_number_debug_dummy,
-	&cl_SV_number_debug_module
-};
+CL_FORCE_LINK(cl_SV_number_debug_dummy, cl_SV_number_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/include/cln/SV_ringelt.h b/include/cln/SV_ringelt.h
index 9d3a501..d5ac3bb 100644
--- a/include/cln/SV_ringelt.h
+++ b/include/cln/SV_ringelt.h
@@ -56,9 +56,7 @@ extern void fprint (std::ostream& stream, const cl_ring& R, const cl_SV_ringelt&
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_SV_ringelt_debug_module;
-static void* const cl_SV_ringelt_debug_dummy[] = { &cl_SV_ringelt_debug_dummy,
-	&cl_SV_ringelt_debug_module
-};
+CL_FORCE_LINK(cl_SV_ringelt_debug_dummy, cl_SV_ringelt_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/include/cln/dfloat.h b/include/cln/dfloat.h
index 57ca98f..b70cb88 100644
--- a/include/cln/dfloat.h
+++ b/include/cln/dfloat.h
@@ -297,9 +297,7 @@ extern cl_class cl_class_dfloat;
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_DF_debug_module;
-static void* const cl_DF_debug_dummy[] = { &cl_DF_debug_dummy,
-	&cl_DF_debug_module
-};
+CL_FORCE_LINK(cl_DF_debug_dummy, cl_DF_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/include/cln/ffloat.h b/include/cln/ffloat.h
index 9782e4d..a107a5e 100644
--- a/include/cln/ffloat.h
+++ b/include/cln/ffloat.h
@@ -293,18 +293,14 @@ CL_REQUIRE(cl_ieee)
 // Runtime typing support.
 extern cl_class cl_class_ffloat;
 #ifdef CL_WIDE_POINTERS
-static const void* const cl_FF_classes_dummy[] = { &cl_FF_classes_dummy,
-	&cl_class_ffloat
-};
+CL_FORCE_LINK(cl_FF_classes_dummy, cl_class_ffloat)
 #endif
 
 
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_FF_debug_module;
-static void* const cl_FF_debug_dummy[] = { &cl_FF_debug_dummy,
-	&cl_FF_debug_module
-};
+CL_FORCE_LINK(cl_FF_debug_dummy, cl_FF_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/include/cln/integer.h b/include/cln/integer.h
index 850cefe..07624fa 100644
--- a/include/cln/integer.h
+++ b/include/cln/integer.h
@@ -586,17 +586,13 @@ inline cl_I& operator%= (cl_I& x, const cl_I& y) { return x = x % y; }
 // Runtime typing support.
 extern cl_class cl_class_fixnum;
 extern cl_class cl_class_bignum;
-static const void* const cl_I_classes_dummy[] = { &cl_I_classes_dummy,
-	&cl_class_fixnum
-};
+CL_FORCE_LINK(cl_I_classes_dummy, cl_class_fixnum)
 
 
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_I_debug_module;
-static void* const cl_I_debug_dummy[] = { &cl_I_debug_dummy,
-	&cl_I_debug_module
-};
+CL_FORCE_LINK(cl_I_debug_dummy, cl_I_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/include/cln/lfloat.h b/include/cln/lfloat.h
index 033ed43..440151b 100644
--- a/include/cln/lfloat.h
+++ b/include/cln/lfloat.h
@@ -403,9 +403,7 @@ extern cl_class cl_class_lfloat;
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_LF_debug_module;
-static void* const cl_LF_debug_dummy[] = { &cl_LF_debug_dummy,
-	&cl_LF_debug_module
-};
+CL_FORCE_LINK(cl_LF_debug_dummy, cl_LF_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/include/cln/modinteger.h b/include/cln/modinteger.h
index cc613be..d339cba 100644
--- a/include/cln/modinteger.h
+++ b/include/cln/modinteger.h
@@ -456,9 +456,7 @@ inline const cl_MI operator* (const cl_MI& x, const cl_I& y)
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_MI_debug_module;
-static void* const cl_MI_debug_dummy[] = { &cl_MI_debug_dummy,
-	&cl_MI_debug_module
-};
+CL_FORCE_LINK(cl_MI_debug_dummy, cl_MI_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/include/cln/modules.h b/include/cln/modules.h
index 22f7c19..b7ff435 100644
--- a/include/cln/modules.h
+++ b/include/cln/modules.h
@@ -248,4 +248,26 @@
   #define CL_REQUIRE(module)
 #endif
 
+// Sometimes a link time dependency is needed, but without requirements
+// on initialization order.
+//
+// CL_FORCE_LINK(dummy,external_variable)
+// forces a link time reference to the external_variable.
+#include <stdlib.h>
+#if 0
+// This definition does not work.  It gets optimized away by g++ 3.1.
+#define CL_FORCE_LINK(dummy,external_variable) \
+  static const void* const dummy[] = { &dummy, &external_variable };
+#else
+#define CL_FORCE_LINK(dummy,external_variable) \
+  static const								\
+  struct dummy {							\
+    inline dummy () {							\
+      if ((void*) &external_variable == (void*) this)			\
+        abort();							\
+    }									\
+  }									\
+  dummy##_instance;
+#endif
+
 #endif /* _CL_MODULES_H */
diff --git a/include/cln/rational.h b/include/cln/rational.h
index 5992572..fdc5beb 100644
--- a/include/cln/rational.h
+++ b/include/cln/rational.h
@@ -294,9 +294,7 @@ extern cl_class cl_class_ratio;
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_RA_debug_module;
-static void* const cl_RA_debug_dummy[] = { &cl_RA_debug_dummy,
-	&cl_RA_debug_module
-};
+CL_FORCE_LINK(cl_RA_debug_dummy, cl_RA_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/include/cln/real.h b/include/cln/real.h
index 5061ced..f29465f 100644
--- a/include/cln/real.h
+++ b/include/cln/real.h
@@ -511,9 +511,7 @@ inline const cl_R conjugate (const cl_R& x)
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_R_debug_module;
-static void* const cl_R_debug_dummy[] = { &cl_R_debug_dummy,
-	&cl_R_debug_module
-};
+CL_FORCE_LINK(cl_R_debug_dummy, cl_R_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/include/cln/ring.h b/include/cln/ring.h
index 70b6120..b282cf3 100644
--- a/include/cln/ring.h
+++ b/include/cln/ring.h
@@ -434,9 +434,7 @@ inline cl_boolean instanceof (const cl_number& x, const cl_number_ring& R)
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_ring_debug_module;
-static void* const cl_ring_debug_dummy[] = { &cl_ring_debug_dummy,
-	&cl_ring_debug_module
-};
+CL_FORCE_LINK(cl_ring_debug_dummy, cl_ring_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/include/cln/sfloat.h b/include/cln/sfloat.h
index 1f69d90..cb3aa96 100644
--- a/include/cln/sfloat.h
+++ b/include/cln/sfloat.h
@@ -288,17 +288,13 @@ inline cl_SF& operator/= (cl_SF& x, const cl_SF& y) { return x = x / y; }
 
 // Runtime typing support.
 extern cl_class cl_class_sfloat;
-static const void* const cl_SF_classes_dummy[] = { &cl_SF_classes_dummy,
-	&cl_class_sfloat
-};
+CL_FORCE_LINK(cl_SF_classes_dummy, cl_class_sfloat)
 
 
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_SF_debug_module;
-static void* const cl_SF_debug_dummy[] = { &cl_SF_debug_dummy,
-	&cl_SF_debug_module
-};
+CL_FORCE_LINK(cl_SF_debug_dummy, cl_SF_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/include/cln/string.h b/include/cln/string.h
index f413f52..2c4239d 100644
--- a/include/cln/string.h
+++ b/include/cln/string.h
@@ -163,9 +163,7 @@ extern cl_class cl_class_string;
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_string_debug_module;
-static void* const cl_string_debug_dummy[] = { &cl_string_debug_dummy,
-	&cl_string_debug_module
-};
+CL_FORCE_LINK(cl_string_debug_dummy, cl_string_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/include/cln/univpoly.h b/include/cln/univpoly.h
index bfc88ac..23bd033 100644
--- a/include/cln/univpoly.h
+++ b/include/cln/univpoly.h
@@ -457,9 +457,7 @@ inline cl_UP::cl_UP ()
 // Debugging support.
 #ifdef CL_DEBUG
 extern int cl_UP_debug_module;
-static void* const cl_UP_debug_dummy[] = { &cl_UP_debug_dummy,
-	&cl_UP_debug_module
-};
+CL_FORCE_LINK(cl_UP_debug_dummy, cl_UP_debug_module)
 #endif
 
 }  // namespace cln
diff --git a/src/float/base/cl_ieee.h b/src/float/base/cl_ieee.h
index 355e667..0081c46 100644
--- a/src/float/base/cl_ieee.h
+++ b/src/float/base/cl_ieee.h
@@ -10,7 +10,7 @@ namespace cln {
 #if (defined(linux) || defined(__linux)) // only needed on Linux
   #define NEED_IEEE_FLOATS()  \
     CL_REQUIRE(cl_ieee)							\
-    static void* const CONCAT(cl_ieee_dummy_,__LINE__) = &cl_ieee_module;
+    CL_FORCE_LINK(CONCAT(cl_ieee_dummy_,__LINE__), cl_ieee_module)
 #else
   #define NEED_IEEE_FLOATS()
 #endif