/* This module handles expression trees.
- Copyright (C) 1991-2016 Free Software Foundation, Inc.
+ Copyright (C) 1991-2017 Free Software Foundation, Inc.
Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
This file is part of the GNU Binutils.
}
}
+/* Arithmetic operators, bitwise AND, bitwise OR and XOR keep the
+ section of one of their operands only when the other operand is a
+ plain number. Losing the section when operating on two symbols,
+ ie. a result of a plain number, is required for subtraction and
+ XOR. It's justifiable for the other operations on the grounds that
+ adding, multiplying etc. two section relative values does not
+ really make sense unless they are just treated as numbers.
+ The same argument could be made for many expressions involving one
+ symbol and a number. For example, "1 << x" and "100 / x" probably
+ should not be given the section of x. The trouble is that if we
+ fuss about such things the rules become complex and it is onerous
+ to document ld expression evaluation. */
+static void
+arith_result_section (const etree_value_type *lhs)
+{
+ if (expld.result.section == lhs->section)
+ {
+ if (expld.section == bfd_abs_section_ptr
+ && !config.sane_expr)
+ /* Duplicate the insanity in exp_fold_tree_1 case etree_value. */
+ expld.result.section = bfd_abs_section_ptr;
+ else
+ expld.result.section = NULL;
+ }
+}
+
static void
fold_binary (etree_type *tree)
{
switch (tree->type.node_code)
{
- /* Arithmetic operators, bitwise AND, bitwise OR and XOR
- keep the section of one of their operands only when the
- other operand is a plain number. Losing the section when
- operating on two symbols, ie. a result of a plain number,
- is required for subtraction and XOR. It's justifiable
- for the other operations on the grounds that adding,
- multiplying etc. two section relative values does not
- really make sense unless they are just treated as
- numbers.
- The same argument could be made for many expressions
- involving one symbol and a number. For example,
- "1 << x" and "100 / x" probably should not be given the
- section of x. The trouble is that if we fuss about such
- things the rules become complex and it is onerous to
- document ld expression evaluation. */
#define BOP(x, y) \
case x: \
expld.result.value = lhs.value y expld.result.value; \
- if (expld.result.section == lhs.section) \
- expld.result.section = NULL; \
+ arith_result_section (&lhs); \
break;
/* Comparison operators, logical AND, and logical OR always
% (bfd_signed_vma) expld.result.value);
else if (expld.phase != lang_mark_phase_enum)
einfo (_("%F%S %% by zero\n"), tree->binary.rhs);
- if (expld.result.section == lhs.section)
- expld.result.section = NULL;
+ arith_result_section (&lhs);
break;
case '/':
/ (bfd_signed_vma) expld.result.value);
else if (expld.phase != lang_mark_phase_enum)
einfo (_("%F%S / by zero\n"), tree->binary.rhs);
- if (expld.result.section == lhs.section)
- expld.result.section = NULL;
+ arith_result_section (&lhs);
break;
case MAX_K:
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;
+ 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);
- }
+ hsrc = bfd_link_hash_lookup (link_info.hash, src->name.name,
+ FALSE, FALSE, TRUE);
+ if (hsrc != NULL)
+ bfd_copy_link_hash_symbol_type (link_info.output_bfd, h, hsrc);
}
static void
before relaxation and so be stripped incorrectly. */
if (expld.phase == lang_mark_phase_enum
&& expld.section != bfd_abs_section_ptr
+ && expld.section != bfd_und_section_ptr
&& !(expld.result.valid_p
&& expld.result.value == 0
&& (is_value (tree->assign.src, 0)
|| is_align_conditional (tree->assign.src))))
expld.section->flags |= SEC_KEEP;
- if (!expld.result.valid_p)
+ if (!expld.result.valid_p
+ || expld.section == bfd_und_section_ptr)
{
if (expld.phase != lang_mark_phase_enum)
einfo (_("%F%S invalid assignment to"
}
}
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
etree_type *
exp_binop (int code, etree_type *lhs, etree_type *rhs)
{
- etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->binary));
-
+ etree_type *new_e = (etree_type *) stat_alloc (MAX (sizeof (new_e->binary),
+ sizeof (new_e->value)));
new_e->type.node_code = code;
new_e->type.filename = lhs->type.filename;
new_e->type.lineno = lhs->type.lineno;
etree_type *
exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
{
- etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->trinary));
-
+ etree_type *new_e = (etree_type *) stat_alloc (MAX (sizeof (new_e->trinary),
+ sizeof (new_e->value)));
new_e->type.node_code = code;
new_e->type.filename = cond->type.filename;
new_e->type.lineno = cond->type.lineno;
etree_type *
exp_unop (int code, etree_type *child)
{
- etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->unary));
-
+ etree_type *new_e = (etree_type *) stat_alloc (MAX (sizeof (new_e->unary),
+ sizeof (new_e->value)));
new_e->unary.type.node_code = code;
new_e->unary.type.filename = child->type.filename;
new_e->unary.type.lineno = child->type.lineno;