testsuite, fortran: fix info-types for intel compilers
[binutils-gdb.git] / gas / symbols.c
index 04017b6744f3c8d901967ab13fa29eeaa431e5b4..e3fddee8c79753e83a406f9f473a560243cd4bbd 100644 (file)
@@ -1,5 +1,5 @@
 /* symbols.c -symbol table-
-   Copyright (C) 1987-2020 Free Software Foundation, Inc.
+   Copyright (C) 1987-2022 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
 #include "subsegs.h"
 #include "write.h"
 
+#include <limits.h>
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
 struct symbol_flags
 {
   /* Whether the symbol is a local_symbol.  */
@@ -56,8 +61,10 @@ struct symbol_flags
   /* Whether the symbol can be re-defined.  */
   unsigned int volatil : 1;
 
-  /* Whether the symbol is a forward reference.  */
+  /* Whether the symbol is a forward reference, and whether such has
+     been determined.  */
   unsigned int forward_ref : 1;
+  unsigned int forward_resolved : 1;
 
   /* This is set if the symbol is defined in an MRI common section.
      We handle such sections as single common symbols, so symbols
@@ -73,6 +80,14 @@ struct symbol_flags
      before.  It is cleared as soon as any direct reference to the
      symbol is present.  */
   unsigned int weakrefd : 1;
+
+  /* Whether the symbol has been marked to be removed by a .symver
+     directive.  */
+  unsigned int removed : 1;
+
+  /* Set when a warning about the symbol containing multibyte characters
+     is generated.  */
+  unsigned int multibyte_warned : 1;
 };
 
 /* A pointer in the symbol may point to either a complete symbol
@@ -189,7 +204,8 @@ static void *
 symbol_entry_find (htab_t table, const char *name)
 {
   hashval_t hash = htab_hash_string (name);
-  symbol_entry_t needle = { { { 0 }, hash, name, 0, 0, 0 } };
+  symbol_entry_t needle = { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+                             hash, name, 0, 0, 0 } };
   return htab_find_with_hash (table, &needle, hash);
 }
 
@@ -232,13 +248,6 @@ struct obstack notes;
 const char * an_external_name;
 #endif
 
-static const char *save_symbol_name (const char *);
-static void fb_label_init (void);
-static long dollar_label_instance (long);
-static long fb_label_instance (long);
-
-static void print_binary (FILE *, const char *, expressionS *);
-
 /* Return a pointer to a new symbol.  Die if we can't make a new
    symbol.  Fill in the symbol's values.  Add symbol to end of symbol
    chain.
@@ -299,6 +308,18 @@ symbol_init (symbolS *symbolP, const char *name, asection *sec,
   symbolP->bsym->name = name;
   symbolP->bsym->section = sec;
 
+  if (multibyte_handling == multibyte_warn_syms
+      && ! symbolP->flags.local_symbol
+      && sec != undefined_section
+      && ! symbolP->flags.multibyte_warned
+      && scan_for_multibyte_characters ((const unsigned char *) name,
+                                       (const unsigned char *) name + strlen (name),
+                                       false /* Do not warn.  */))
+    {
+      as_warn (_("symbol '%s' contains multibyte characters"), name);
+      symbolP->flags.multibyte_warned = 1;
+    }
+
   S_SET_VALUE (symbolP, valu);
 
   symbol_clear_list_pointers (symbolP);
@@ -758,7 +779,9 @@ symbol_clone (symbolS *orgsymP, int replace)
 symbolS *
 symbol_clone_if_forward_ref (symbolS *symbolP, int is_forward)
 {
-  if (symbolP && !symbolP->flags.local_symbol)
+  if (symbolP
+      && !symbolP->flags.local_symbol
+      && !symbolP->flags.forward_resolved)
     {
       symbolS *orig_add_symbol = symbolP->x->value.X_add_symbol;
       symbolS *orig_op_symbol = symbolP->x->value.X_op_symbol;
@@ -811,6 +834,7 @@ symbol_clone_if_forward_ref (symbolS *symbolP, int is_forward)
 
       symbolP->x->value.X_add_symbol = add_symbol;
       symbolP->x->value.X_op_symbol = op_symbol;
+      symbolP->flags.forward_resolved = 1;
     }
 
   return symbolP;
@@ -1340,6 +1364,7 @@ resolve_symbol_value (symbolS *symp)
 
        case O_symbol:
        case O_symbol_rva:
+       case O_secidx:
          left = resolve_symbol_value (add_symbol);
          seg_left = S_GET_SEGMENT (add_symbol);
          if (finalize_syms)
@@ -1374,7 +1399,17 @@ resolve_symbol_value (symbolS *symp)
              && add_symbol->flags.resolving)
            break;
 
-         if (finalize_syms && final_val == 0)
+         if (finalize_syms && final_val == 0
+#ifdef OBJ_XCOFF
+             /* Avoid changing symp's "within" when dealing with
+                AIX debug symbols. For some storage classes, "within"
+                have a special meaning.
+                C_DWARF should behave like on Linux, thus this check
+                isn't done to be closer.  */
+             && ((symbol_get_bfdsym (symp)->flags & BSF_DEBUGGING) == 0
+                 || (S_GET_STORAGE_CLASS (symp) == C_DWARF))
+#endif
+             )
            {
              if (add_symbol->flags.local_symbol)
                add_symbol = local_symbol_convert (add_symbol);
@@ -1410,6 +1445,13 @@ resolve_symbol_value (symbolS *symp)
              final_val += symp->frag->fr_address + left;
              resolved = symbol_resolved_p (add_symbol);
              symp->flags.resolving = 0;
+
+             if (op == O_secidx && seg_left != undefined_section)
+               {
+                 final_val = 0;
+                 break;
+               }
+
              goto exit_dont_set_value;
            }
          else
@@ -1559,14 +1601,24 @@ resolve_symbol_value (symbolS *symp)
 
              right = 1;
            }
+         if ((op == O_left_shift || op == O_right_shift)
+             && (valueT) right >= sizeof (valueT) * CHAR_BIT)
+           {
+             as_warn_value_out_of_range (_("shift count"), right, 0,
+                                         sizeof (valueT) * CHAR_BIT - 1,
+                                         NULL, 0);
+             left = right = 0;
+           }
 
          switch (symp->x->value.X_op)
            {
            case O_multiply:            left *= right; break;
            case O_divide:              left /= right; break;
            case O_modulus:             left %= right; break;
-           case O_left_shift:          left <<= right; break;
-           case O_right_shift:         left >>= right; break;
+           case O_left_shift:
+             left = (valueT) left << (valueT) right; break;
+           case O_right_shift:
+             left = (valueT) left >> (valueT) right; break;
            case O_bit_inclusive_or:    left |= right; break;
            case O_bit_or_not:          left |= ~right; break;
            case O_bit_exclusive_or:    left ^= right; break;
@@ -1758,16 +1810,17 @@ snapshot_symbol (symbolS **symbolPP, valueT *valueP, segT *segP, fragS **fragPP)
    the instance number, keep a list of defined symbols separate from the real
    symbol table, and we treat these buggers as a sparse array.  */
 
-static long *dollar_labels;
-static long *dollar_label_instances;
+typedef unsigned int dollar_ent;
+static dollar_ent *dollar_labels;
+static dollar_ent *dollar_label_instances;
 static char *dollar_label_defines;
-static unsigned long dollar_label_count;
-static unsigned long dollar_label_max;
+static size_t dollar_label_count;
+static size_t dollar_label_max;
 
 int
-dollar_label_defined (long label)
+dollar_label_defined (unsigned int label)
 {
-  long *i;
+  dollar_ent *i;
 
   know ((dollar_labels != NULL) || (dollar_label_count == 0));
 
@@ -1779,10 +1832,10 @@ dollar_label_defined (long label)
   return 0;
 }
 
-static long
-dollar_label_instance (long label)
+static unsigned int
+dollar_label_instance (unsigned int label)
 {
-  long *i;
+  dollar_ent *i;
 
   know ((dollar_labels != NULL) || (dollar_label_count == 0));
 
@@ -1798,15 +1851,16 @@ dollar_label_instance (long label)
 void
 dollar_label_clear (void)
 {
-  memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count);
+  if (dollar_label_count)
+    memset (dollar_label_defines, '\0', dollar_label_count);
 }
 
 #define DOLLAR_LABEL_BUMP_BY 10
 
 void
-define_dollar_label (long label)
+define_dollar_label (unsigned int label)
 {
-  long *i;
+  dollar_ent *i;
 
   for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
     if (*i == label)
@@ -1820,8 +1874,8 @@ define_dollar_label (long label)
 
   if (dollar_labels == NULL)
     {
-      dollar_labels = XNEWVEC (long, DOLLAR_LABEL_BUMP_BY);
-      dollar_label_instances = XNEWVEC (long, DOLLAR_LABEL_BUMP_BY);
+      dollar_labels = XNEWVEC (dollar_ent, DOLLAR_LABEL_BUMP_BY);
+      dollar_label_instances = XNEWVEC (dollar_ent, DOLLAR_LABEL_BUMP_BY);
       dollar_label_defines = XNEWVEC (char, DOLLAR_LABEL_BUMP_BY);
       dollar_label_max = DOLLAR_LABEL_BUMP_BY;
       dollar_label_count = 0;
@@ -1829,9 +1883,11 @@ define_dollar_label (long label)
   else if (dollar_label_count == dollar_label_max)
     {
       dollar_label_max += DOLLAR_LABEL_BUMP_BY;
-      dollar_labels = XRESIZEVEC (long, dollar_labels, dollar_label_max);
-      dollar_label_instances = XRESIZEVEC (long, dollar_label_instances,
-                                         dollar_label_max);
+      dollar_labels = XRESIZEVEC (dollar_ent, dollar_labels,
+                                 dollar_label_max);
+      dollar_label_instances = XRESIZEVEC (dollar_ent,
+                                          dollar_label_instances,
+                                          dollar_label_max);
       dollar_label_defines = XRESIZEVEC (char, dollar_label_defines,
                                         dollar_label_max);
     }                          /* if we needed to grow  */
@@ -1851,50 +1907,22 @@ define_dollar_label (long label)
    symbol. The first "4:" is "L4^A1" - the m numbers begin at 1.
 
    fb labels get the same treatment, except that ^B is used in place
-   of ^A.  */
+   of ^A.
+
+   AUGEND is 0 for current instance, 1 for new instance.  */
 
-char *                         /* Return local label name.  */
-dollar_label_name (long n,     /* we just saw "n$:" : n a number.  */
-                  int augend   /* 0 for current instance, 1 for new instance.  */)
+char *
+dollar_label_name (unsigned int n, unsigned int augend)
 {
-  long i;
   /* Returned to caller, then copied.  Used for created names ("4f").  */
   static char symbol_name_build[24];
-  char *p;
-  char *q;
-  char symbol_name_temporary[20];      /* Build up a number, BACKWARDS.  */
+  char *p = symbol_name_build;
 
-  know (n >= 0);
-  know (augend == 0 || augend == 1);
-  p = symbol_name_build;
 #ifdef LOCAL_LABEL_PREFIX
   *p++ = LOCAL_LABEL_PREFIX;
 #endif
-  *p++ = 'L';
-
-  /* Next code just does sprintf( {}, "%d", n);  */
-  /* Label number.  */
-  q = symbol_name_temporary;
-  for (*q++ = 0, i = n; i; ++q)
-    {
-      *q = i % 10 + '0';
-      i /= 10;
-    }
-  while ((*p = *--q) != '\0')
-    ++p;
-
-  *p++ = DOLLAR_LABEL_CHAR;            /* ^A  */
-
-  /* Instance number.  */
-  q = symbol_name_temporary;
-  for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q)
-    {
-      *q = i % 10 + '0';
-      i /= 10;
-    }
-  while ((*p++ = *--q) != '\0');
-
-  /* The label, as a '\0' ended string, starts at symbol_name_build.  */
+  sprintf (p, "L%u%c%u",
+          n, DOLLAR_LABEL_CHAR, dollar_label_instance (n) + augend);
   return symbol_name_build;
 }
 
@@ -1917,11 +1945,12 @@ dollar_label_name (long n,      /* we just saw "n$:" : n a number.  */
 
 #define FB_LABEL_SPECIAL (10)
 
-static long fb_low_counter[FB_LABEL_SPECIAL];
-static long *fb_labels;
-static long *fb_label_instances;
-static long fb_label_count;
-static long fb_label_max;
+typedef unsigned int fb_ent;
+static fb_ent fb_low_counter[FB_LABEL_SPECIAL];
+static fb_ent *fb_labels;
+static fb_ent *fb_label_instances;
+static size_t fb_label_count;
+static size_t fb_label_max;
 
 /* This must be more than FB_LABEL_SPECIAL.  */
 #define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6)
@@ -1935,11 +1964,11 @@ fb_label_init (void)
 /* Add one to the instance number of this fb label.  */
 
 void
-fb_label_instance_inc (long label)
+fb_label_instance_inc (unsigned int label)
 {
-  long *i;
+  fb_ent *i;
 
-  if ((unsigned long) label < FB_LABEL_SPECIAL)
+  if (label < FB_LABEL_SPECIAL)
     {
       ++fb_low_counter[label];
       return;
@@ -1962,8 +1991,8 @@ fb_label_instance_inc (long label)
 
   if (fb_labels == NULL)
     {
-      fb_labels = XNEWVEC (long, FB_LABEL_BUMP_BY);
-      fb_label_instances = XNEWVEC (long, FB_LABEL_BUMP_BY);
+      fb_labels = XNEWVEC (fb_ent, FB_LABEL_BUMP_BY);
+      fb_label_instances = XNEWVEC (fb_ent, FB_LABEL_BUMP_BY);
       fb_label_max = FB_LABEL_BUMP_BY;
       fb_label_count = FB_LABEL_SPECIAL;
 
@@ -1971,8 +2000,9 @@ fb_label_instance_inc (long label)
   else if (fb_label_count == fb_label_max)
     {
       fb_label_max += FB_LABEL_BUMP_BY;
-      fb_labels = XRESIZEVEC (long, fb_labels, fb_label_max);
-      fb_label_instances = XRESIZEVEC (long, fb_label_instances, fb_label_max);
+      fb_labels = XRESIZEVEC (fb_ent, fb_labels, fb_label_max);
+      fb_label_instances = XRESIZEVEC (fb_ent, fb_label_instances,
+                                      fb_label_max);
     }                          /* if we needed to grow  */
 
   fb_labels[fb_label_count] = label;
@@ -1980,15 +2010,13 @@ fb_label_instance_inc (long label)
   ++fb_label_count;
 }
 
-static long
-fb_label_instance (long label)
+static unsigned int
+fb_label_instance (unsigned int label)
 {
-  long *i;
+  fb_ent *i;
 
-  if ((unsigned long) label < FB_LABEL_SPECIAL)
-    {
-      return (fb_low_counter[label]);
-    }
+  if (label < FB_LABEL_SPECIAL)
+    return (fb_low_counter[label]);
 
   if (fb_labels != NULL)
     {
@@ -1996,10 +2024,8 @@ fb_label_instance (long label)
           i < fb_labels + fb_label_count; ++i)
        {
          if (*i == label)
-           {
-             return (fb_label_instances[i - fb_labels]);
-           }                   /* if we find it  */
-       }                       /* for each existing label  */
+           return (fb_label_instances[i - fb_labels]);
+       }
     }
 
   /* We didn't find the label, so this must be a reference to the
@@ -2016,55 +2042,29 @@ fb_label_instance (long label)
    symbol. The first "4:" is "L4^B1" - the m numbers begin at 1.
 
    dollar labels get the same treatment, except that ^A is used in
-   place of ^B.  */
+   place of ^B.
 
-char *                         /* Return local label name.  */
-fb_label_name (long n, /* We just saw "n:", "nf" or "nb" : n a number.  */
-              long augend      /* 0 for nb, 1 for n:, nf.  */)
+   AUGEND is 0 for nb, 1 for n:, nf.  */
+
+char *
+fb_label_name (unsigned int n, unsigned int augend)
 {
-  long i;
   /* Returned to caller, then copied.  Used for created names ("4f").  */
   static char symbol_name_build[24];
-  char *p;
-  char *q;
-  char symbol_name_temporary[20];      /* Build up a number, BACKWARDS.  */
+  char *p = symbol_name_build;
 
-  know (n >= 0);
 #ifdef TC_MMIX
-  know ((unsigned long) augend <= 2 /* See mmix_fb_label.  */);
+  know (augend <= 2 /* See mmix_fb_label.  */);
 #else
-  know ((unsigned long) augend <= 1);
+  know (augend <= 1);
 #endif
-  p = symbol_name_build;
+
 #ifdef LOCAL_LABEL_PREFIX
   *p++ = LOCAL_LABEL_PREFIX;
 #endif
-  *p++ = 'L';
-
-  /* Next code just does sprintf( {}, "%d", n);  */
-  /* Label number.  */
-  q = symbol_name_temporary;
-  for (*q++ = 0, i = n; i; ++q)
-    {
-      *q = i % 10 + '0';
-      i /= 10;
-    }
-  while ((*p = *--q) != '\0')
-    ++p;
-
-  *p++ = LOCAL_LABEL_CHAR;             /* ^B  */
-
-  /* Instance number.  */
-  q = symbol_name_temporary;
-  for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q)
-    {
-      *q = i % 10 + '0';
-      i /= 10;
-    }
-  while ((*p++ = *--q) != '\0');
-
-  /* The label, as a '\0' ended string, starts at symbol_name_build.  */
-  return (symbol_name_build);
+  sprintf (p, "L%u%c%u",
+          n, LOCAL_LABEL_CHAR, fb_label_instance (n) + augend);
+  return symbol_name_build;
 }
 
 /* Decode name that may have been generated by foo_label_name() above.
@@ -2275,7 +2275,7 @@ S_FORCE_RELOC (symbolS *s, int strict)
               || (EXTERN_FORCE_RELOC
                   && (s->bsym->flags & BSF_GLOBAL) != 0)))
          || (s->bsym->flags & BSF_GNU_INDIRECT_FUNCTION) != 0)
-       return TRUE;
+       return true;
       sec = s->bsym->section;
     }
   return bfd_is_und_section (sec) || bfd_is_com_section (sec);
@@ -2396,7 +2396,21 @@ S_SET_SEGMENT (symbolS *s, segT seg)
        abort ();
     }
   else
-    s->bsym->section = seg;
+    {
+      if (multibyte_handling == multibyte_warn_syms
+         && ! s->flags.local_symbol
+         && seg != undefined_section
+         && ! s->flags.multibyte_warned
+         && scan_for_multibyte_characters ((const unsigned char *) s->name,
+                                           (const unsigned char *) s->name + strlen (s->name),
+                                           false))
+       {
+         as_warn (_("symbol '%s' contains multibyte characters"), s->name);
+         s->flags.multibyte_warned = 1;
+       }
+
+      s->bsym->section = seg;
+    }
 }
 
 void
@@ -2412,14 +2426,13 @@ S_SET_EXTERNAL (symbolS *s)
   if (s->bsym->flags & BSF_SECTION_SYM)
     {
       /* Do not reassign section symbols.  */
-      as_warn (_("section symbols are already global"));
+      as_warn (_("can't make section symbol global"));
       return;
     }
 #ifndef TC_GLOBAL_REGISTER_SYMBOL_OK
   if (S_GET_SEGMENT (s) == reg_section)
     {
-      as_bad ("can't make register symbol `%s' global",
-             S_GET_NAME (s));
+      as_bad (_("can't make register symbol global"));
       return;
     }
 #endif
@@ -2781,6 +2794,26 @@ symbol_written_p (symbolS *s)
   return s->flags.written;
 }
 
+/* Mark a symbol as to be removed.  */
+
+void
+symbol_mark_removed (symbolS *s)
+{
+  if (s->flags.local_symbol)
+    return;
+  s->flags.removed = 1;
+}
+
+/* Return whether a symbol has been marked to be removed.  */
+
+int
+symbol_removed_p (symbolS *s)
+{
+  if (s->flags.local_symbol)
+    return 0;
+  return s->flags.removed;
+}
+
 /* Mark a symbol has having been resolved.  */
 
 void
@@ -2990,7 +3023,7 @@ print_symbol_value_1 (FILE *file, symbolS *sym)
   if (!name || !name[0])
     name = "(unnamed)";
   fprintf (file, "sym ");
-  fprintf_vma (file, (bfd_vma) ((bfd_hostptr_t) sym));
+  fprintf_vma (file, (bfd_vma) (uintptr_t) sym);
   fprintf (file, " %s", name);
 
   if (sym->flags.local_symbol)
@@ -3001,7 +3034,7 @@ print_symbol_value_1 (FILE *file, symbolS *sym)
          && locsym->frag != NULL)
        {
          fprintf (file, " frag ");
-         fprintf_vma (file, (bfd_vma) ((bfd_hostptr_t) locsym->frag));
+         fprintf_vma (file, (bfd_vma) (uintptr_t) locsym->frag);
        }
       if (locsym->flags.resolved)
        fprintf (file, " resolved");
@@ -3012,7 +3045,7 @@ print_symbol_value_1 (FILE *file, symbolS *sym)
       if (sym->frag != &zero_address_frag)
        {
          fprintf (file, " frag ");
-         fprintf_vma (file, (bfd_vma) ((bfd_hostptr_t) sym->frag));
+         fprintf_vma (file, (bfd_vma) (uintptr_t) sym->frag);
        }
       if (sym->flags.written)
        fprintf (file, " written");
@@ -3088,7 +3121,7 @@ void
 print_expr_1 (FILE *file, expressionS *exp)
 {
   fprintf (file, "expr ");
-  fprintf_vma (file, (bfd_vma) ((bfd_hostptr_t) exp));
+  fprintf_vma (file, (bfd_vma) (uintptr_t) exp);
   fprintf (file, " ");
   switch (exp->X_op)
     {