]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
go-gcc.cc (Gcc_backend::immutable_struct): If IS_COMMON, set DECL_WEAK.
authorIan Lance Taylor <iant@google.com>
Tue, 4 Mar 2014 02:56:57 +0000 (02:56 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 4 Mar 2014 02:56:57 +0000 (02:56 +0000)
* go-gcc.cc (Gcc_backend::immutable_struct): If IS_COMMON, set
DECL_WEAK.
(GCC_backend::immutable_struct_set_init): If IS_COMMON, clear
DECL_WEAK.

From-SVN: r208301

gcc/go/ChangeLog
gcc/go/go-gcc.cc

index c571d4d5a4b0767ada40ee05259b18da7f4bbdce..689578e2064608342b4c24ca0e21a854f3cf5364 100644 (file)
@@ -1,3 +1,10 @@
+2014-03-03  Ian Lance Taylor  <iant@google.com>
+
+       * go-gcc.cc (Gcc_backend::immutable_struct): If IS_COMMON, set
+       DECL_WEAK.
+       (GCC_backend::immutable_struct_set_init): If IS_COMMON, clear
+       DECL_WEAK.
+
 2014-01-24  Chris Manghane  <cmang@google.com>
 
        * go-gcc.cc (Gcc_backend::unary_expression): New function.
index b2760f131d84f8a0c2b021deeda55727e5c61e01..6aec2877d7b450e5287d5da9c1844d2d1f72c0a4 100644 (file)
@@ -1871,7 +1871,7 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
 
 Bvariable*
 Gcc_backend::immutable_struct(const std::string& name, bool is_hidden,
-                             bool, Btype* btype, Location location)
+                             bool is_common, Btype* btype, Location location)
 {
   tree type_tree = btype->get_tree();
   if (type_tree == error_mark_node)
@@ -1888,6 +1888,21 @@ Gcc_backend::immutable_struct(const std::string& name, bool is_hidden,
   if (!is_hidden)
     TREE_PUBLIC(decl) = 1;
 
+  // When the initializer for one immutable_struct refers to another,
+  // it needs to know the visibility of the referenced struct so that
+  // compute_reloc_for_constant will return the right value.  On many
+  // systems calling make_decl_one_only will mark the decl as weak,
+  // which will change the return value of compute_reloc_for_constant.
+  // We can't reliably call make_decl_one_only yet, because we don't
+  // yet know the initializer.  This issue doesn't arise in C because
+  // Go initializers, unlike C initializers, can be indirectly
+  // recursive.  To ensure that compute_reloc_for_constant computes
+  // the right value if some other initializer refers to this one, we
+  // mark this symbol as weak here.  We undo that below in
+  // immutable_struct_set_init before calling mark_decl_one_only.
+  if (is_common)
+    DECL_WEAK(decl) = 1;
+
   // We don't call rest_of_decl_compilation until we have the
   // initializer.
 
@@ -1910,9 +1925,13 @@ Gcc_backend::immutable_struct_set_init(Bvariable* var, const std::string&,
 
   DECL_INITIAL(decl) = init_tree;
 
-  // We can't call make_decl_one_only until we set DECL_INITIAL.
+  // Now that DECL_INITIAL is set, we can't call make_decl_one_only.
+  // See the comment where DECL_WEAK is set in immutable_struct.
   if (is_common)
-    make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl));
+    {
+      DECL_WEAK(decl) = 0;
+      make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl));
+    }
 
   // These variables are often unneeded in the final program, so put
   // them in their own section so that linker GC can discard them.