When evaluating a ternary operator in a linker script, copy the symbol flags.
authorSimon Dardis <Simon.Dardis@imgtec.com>
Thu, 15 Oct 2015 12:28:27 +0000 (13:28 +0100)
committerNick Clifton <nickc@redhat.com>
Thu, 15 Oct 2015 12:28:27 +0000 (13:28 +0100)
* ld/ldexp.c: (try_copy_symbol_flags): New. Factored out from...
(exp_fold_tree_1): Here.  Cope with ternary operator in
assignments.  Use new helper.

ld/ChangeLog
ld/ldexp.c

index 61a21be..fcae5a0 100644 (file)
@@ -1,3 +1,9 @@
+2015-10-15  Simon Dardis  <Simon.Dardis@imgtec.com>
+
+       * ld/ldexp.c: (try_copy_symbol_flags): New. Factored out from...
+       (exp_fold_tree_1): Here.  Cope with ternary operator in
+       assignments.  Use new helper.
+
 2015-10-14  Nick Clifton  <nickc@redhat.com>
 
        * po/zh_TW.po: Updated Chinese translation.
index b7b6e6c..7694f7b 100644 (file)
@@ -973,7 +973,24 @@ is_align_conditional (const etree_type *tree)
              && is_dot_ne_0 (tree->trinary.cond)
              && is_value (tree->trinary.rhs, 1));
     }
-  return 0;
+  return FALSE;
+}
+
+/* Subroutine of exp_fold_tree_1 for copying a symbol type.  */
+
+static void
+try_copy_symbol_type (struct bfd_link_hash_entry * h, etree_type *src)
+{
+  if (src->type.node_class == etree_name)
+    {
+      struct bfd_link_hash_entry *hsrc;
+
+      hsrc = bfd_link_hash_lookup (link_info.hash, src->name.name,
+                                   FALSE, FALSE, TRUE);
+      if (hsrc)
+       bfd_copy_link_hash_symbol_type (link_info.output_bfd, h,
+                                                   hsrc);
+    }
 }
 
 static void
@@ -1166,18 +1183,25 @@ exp_fold_tree_1 (etree_type *tree)
                tree->type.node_class = etree_provided;
 
              /* Copy the symbol type if this is a simple assignment of
-                one symbol to another.  This could be more general
-                (e.g. a ?: operator with NAMEs in each branch).  */
+                one symbol to another.  Also, handle the case of a foldable
+                ternary conditional with names on either side.  */
              if (tree->assign.src->type.node_class == etree_name)
+               try_copy_symbol_type (h, tree->assign.src);
+             else if (tree->assign.src->type.node_class == etree_trinary)
                {
-                 struct bfd_link_hash_entry *hsrc;
-
-                 hsrc = bfd_link_hash_lookup (link_info.hash,
-                                              tree->assign.src->name.name,
-                                              FALSE, FALSE, TRUE);
-                 if (hsrc)
-                   bfd_copy_link_hash_symbol_type (link_info.output_bfd, h,
-                                                   hsrc);
+                 exp_fold_tree_1 (tree->assign.src->trinary.cond);
+                 if (expld.result.valid_p)
+                   {
+                     if (expld.result.value
+                         && tree->assign.src->trinary.lhs->type.node_class
+                            == etree_name)
+                       try_copy_symbol_type (h, tree->assign.src->trinary.lhs);
+
+                     if (!expld.result.value
+                         && tree->assign.src->trinary.rhs->type.node_class
+                            == etree_name)
+                       try_copy_symbol_type (h, tree->assign.src->trinary.rhs);
+                   }
                }
            }
          else if (expld.phase == lang_final_phase_enum)