]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[gdb/symtab] Factor out new_symbol variant
authorTom de Vries <tdevries@suse.de>
Tue, 28 Apr 2026 16:23:55 +0000 (18:23 +0200)
committerTom de Vries <tdevries@suse.de>
Tue, 28 Apr 2026 16:23:55 +0000 (18:23 +0200)
Factor out a new_symbol variant out of new_symbol, containing mostly the
die->tag switch.

While we're at it, modernize the code using bool and nullptr.  Also, remove
some unnecessary braces, and apply this simplification:
...
if (c)
   foo (a);
else
   foo (b);
->
foo (c
     ? a
     : b);
...

I wondered about naming the new variant new_symbol_tag or new_symbol_1, but
I stuck with new_symbol.

Refactoring made we wonder why we use linkagename instead of sym->linkagename ()
after sym->set_linkage_name (), but since there are cornercases where these are
different, I've left it as is.

Also, I suspect the cp_scan_for_anonymous_namespaces can be hoisted, but I
also left that as is.

Finally, I noticed that physname == linkagename uses a pointer equivalence
test, which seems fragile to me.  Also that I left as is.

The patch is easier to view with git show -w.

Approved-By: Tom Tromey <tom@tromey.com>
gdb/dwarf2/read.c

index 890a36809f7b64559fcf3de9c09f922276b5919d..1288c076aba10381b838ba621ff721d69f7218ca 100644 (file)
@@ -15484,497 +15484,494 @@ new_symbol_file_line (struct die_info *die, struct dwarf2_cu *cu,
   sym->set_symtab (fe->symtab (*file_cu));
 }
 
-/* Given a pointer to a DWARF information entry, figure out if we need
-   to make a symbol table entry for it, and if so, create a new entry
-   and return a pointer to it.
-   If TYPE is NULL, determine symbol type from the die, otherwise
-   used the passed type.
-   If SPACE is not NULL, use it to hold the new symbol.  If it is
-   NULL, allocate a new symbol on the objfile's obstack.  */
+/* Given a DWARF information entry CU/DIE with LINKAGENAME and PHYSNAME, fill
+   in SYM according to DIE->tag.  */
 
-static struct symbol *
-new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
-           struct symbol *space)
+static void
+new_symbol (struct die_info *die, struct dwarf2_cu *cu, struct symbol *sym,
+           const char *linkagename, const char *physname)
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
   struct objfile *objfile = per_objfile->objfile;
-  struct symbol *sym = NULL;
-  const char *name;
-  struct attribute *attr = NULL;
-  struct attribute *attr2 = NULL;
+  struct attribute *attr = nullptr;
+  struct attribute *attr2 = nullptr;
   std::vector<symbol *> *list_to_add = nullptr;
+  bool suppress_add = false;
 
-  name = dwarf2_name (die, cu);
-  if (name == nullptr && (die->tag == DW_TAG_subprogram
-                         || die->tag == DW_TAG_inlined_subroutine
-                         || die->tag == DW_TAG_entry_point))
-    name = dw2_linkage_name (die, cu);
-
-  if (name)
+  switch (die->tag)
     {
-      int suppress_add = 0;
-
-      if (space)
-       sym = space;
-      else
-       sym = objfile->new_symbol<symbol> ();
-
-      /* Cache this symbol's name and the name's demangled form (if any).  */
-      sym->set_language (cu->lang (), &objfile->objfile_obstack);
-      /* Fortran does not have mangling standard and the mangling does differ
-        between gfortran, iFort etc.  */
-      const char *physname
-       = ((cu->lang () == language_fortran || cu->lang () == language_ada)
-          ? dwarf2_full_name (name, die, cu)
-          : dwarf2_physname (name, die, cu));
-      const char *linkagename = dw2_linkage_name (die, cu);
-
-      if (linkagename == nullptr)
-       sym->set_linkage_name (physname);
-      else if (cu->lang () == language_ada)
-       sym->set_linkage_name (linkagename);
+    case DW_TAG_label:
+      {
+       attr = dwarf2_attr (die, DW_AT_low_pc, cu);
+       if (attr != nullptr)
+         {
+           CORE_ADDR addr = per_objfile->relocate (attr->as_address ());
+           sym->set_section_index (SECT_OFF_TEXT (objfile));
+           sym->set_value_address (addr);
+           sym->set_loc_class_index (LOC_LABEL);
+         }
+       else
+         sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
+       type_allocator alloc (objfile, cu->lang ());
+       struct type *addr_type
+         = alloc.copy_type (builtin_type (objfile)->builtin_core_addr);
+       sym->set_type (addr_type);
+       sym->set_domain (LABEL_DOMAIN);
+       list_to_add = cu->list_in_scope;
+      }
+      break;
+    case DW_TAG_entry_point:
+      /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
+        finish_block.  */
+      sym->set_domain (FUNCTION_DOMAIN);
+      sym->set_loc_class_index (LOC_BLOCK);
+      /* DW_TAG_entry_point provides an additional entry_point to an
+        existing sub_program.  Therefore, we inherit the "external"
+        attribute from the sub_program to which the entry_point
+        belongs to.  */
+      attr2 = dwarf2_attr (die->parent, DW_AT_external, cu);
+      if (attr2 != nullptr && attr2->as_boolean ())
+       list_to_add = &cu->get_builder ()->get_global_symbols ();
       else
+       list_to_add = cu->list_in_scope;
+      break;
+    case DW_TAG_subprogram:
+      /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
+        finish_block.  */
+      sym->set_domain (FUNCTION_DOMAIN);
+      sym->set_loc_class_index (LOC_BLOCK);
+      attr2 = dwarf2_attr (die, DW_AT_external, cu);
+      if ((attr2 != nullptr && attr2->as_boolean ())
+         || cu->lang () == language_ada
+         || cu->lang () == language_fortran)
        {
-         if (physname == linkagename)
-           sym->set_demangled_name (name, &objfile->objfile_obstack);
-         else
-           sym->set_demangled_name (physname, &objfile->objfile_obstack);
-
-         sym->set_linkage_name (linkagename);
+         /* Subprograms marked external are stored as a global symbol.
+            Ada and Fortran subprograms, whether marked external or
+            not, are always stored as a global symbol, because we want
+            to be able to access them globally.  For instance, we want
+            to be able to break on a nested subprogram without having
+            to specify the context.  */
+         list_to_add = &cu->get_builder ()->get_global_symbols ();
        }
-
-      /* Handle DW_AT_artificial.  */
-      attr = dwarf2_attr (die, DW_AT_artificial, cu);
-      if (attr != nullptr)
-       sym->set_is_artificial (attr->as_boolean ());
-
-      /* Default assumptions.
-        Use the passed type or decode it from the die.  */
-      sym->set_domain (UNDEF_DOMAIN);
-      sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
-      if (type != NULL)
-       sym->set_type (type);
       else
-       sym->set_type (die_type (die, cu));
+       list_to_add = cu->list_in_scope;
 
-      /* Handle DW_AT_{call,decl}_{file,line}.  */
-      new_symbol_file_line (die, cu, sym);
-
-      switch (die->tag)
+      if (is_ada_import_or_export (cu, physname, linkagename))
        {
-       case DW_TAG_label:
-         {
-           attr = dwarf2_attr (die, DW_AT_low_pc, cu);
-           if (attr != nullptr)
-             {
-               CORE_ADDR addr = per_objfile->relocate (attr->as_address ());
-               sym->set_section_index (SECT_OFF_TEXT (objfile));
-               sym->set_value_address (addr);
-               sym->set_loc_class_index (LOC_LABEL);
-             }
-           else
-             sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
-           type_allocator alloc (objfile, cu->lang ());
-           struct type *addr_type
-             = alloc.copy_type (builtin_type (objfile)->builtin_core_addr);
-           sym->set_type (addr_type);
-           sym->set_domain (LABEL_DOMAIN);
-           list_to_add = cu->list_in_scope;
-         }
-         break;
-       case DW_TAG_entry_point:
-         /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
-            finish_block.  */
-         sym->set_domain (FUNCTION_DOMAIN);
-         sym->set_loc_class_index (LOC_BLOCK);
-         /* DW_TAG_entry_point provides an additional entry_point to an
-            existing sub_program.  Therefore, we inherit the "external"
-            attribute from the sub_program to which the entry_point
-            belongs to.  */
-         attr2 = dwarf2_attr (die->parent, DW_AT_external, cu);
-         if (attr2 != nullptr && attr2->as_boolean ())
-           list_to_add = &cu->get_builder ()->get_global_symbols ();
-         else
-           list_to_add = cu->list_in_scope;
-         break;
-       case DW_TAG_subprogram:
-         /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
-            finish_block.  */
-         sym->set_domain (FUNCTION_DOMAIN);
-         sym->set_loc_class_index (LOC_BLOCK);
-         attr2 = dwarf2_attr (die, DW_AT_external, cu);
-         if ((attr2 != nullptr && attr2->as_boolean ())
-             || cu->lang () == language_ada
-             || cu->lang () == language_fortran)
+         /* This is either a Pragma Import or Export.  They can
+            be distinguished by the declaration flag.  */
+         sym->set_linkage_name (physname);
+         if (die_is_declaration (die, cu))
            {
-             /* Subprograms marked external are stored as a global symbol.
-                Ada and Fortran subprograms, whether marked external or
-                not, are always stored as a global symbol, because we want
-                to be able to access them globally.  For instance, we want
-                to be able to break on a nested subprogram without having
-                to specify the context.  */
-             list_to_add = &cu->get_builder ()->get_global_symbols ();
+             /* For Import, create a symbol using the source
+                name, and have it refer to the linkage name.  */
+             SYMBOL_LOCATION_BATON (sym) = (void *) linkagename;
+             sym->set_loc_class_index (ada_block_index);
            }
          else
            {
-             list_to_add = cu->list_in_scope;
+             /* For Export, create a symbol using the source
+                name, then create a second symbol that refers
+                back to it.  */
+             add_ada_export_symbol (sym, linkagename, physname, cu,
+                                    *list_to_add);
            }
+       }
+      break;
+    case DW_TAG_inlined_subroutine:
+      /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
+        finish_block.  */
+      sym->set_domain (FUNCTION_DOMAIN);
+      sym->set_loc_class_index (LOC_BLOCK);
+      sym->set_is_inlined (1);
+      list_to_add = cu->list_in_scope;
+      break;
+    case DW_TAG_template_value_param:
+      suppress_add = true;
+      [[fallthrough]];
+    case DW_TAG_constant:
+    case DW_TAG_variable:
+    case DW_TAG_member:
+      sym->set_domain (VAR_DOMAIN);
+      /* Compilation with minimal debug info may result in
+        variables with missing type entries.  Change the
+        misleading `void' type to something sensible.  */
+      if (sym->type ()->code () == TYPE_CODE_VOID)
+       {
+         type_allocator alloc (objfile, cu->lang ());
+         struct type *int_type
+           = alloc.copy_type (builtin_type (objfile)->builtin_int);
+         sym->set_type (int_type);
+       }
 
-         if (is_ada_import_or_export (cu, physname, linkagename))
+      attr = dwarf2_attr (die, DW_AT_const_value, cu);
+      /* In the case of DW_TAG_member, we should only be called for
+        static const members.  */
+      if (die->tag == DW_TAG_member)
+       {
+         /* dwarf2_add_field uses die_is_declaration,
+            so we do the same.  */
+         gdb_assert (die_is_declaration (die, cu));
+         gdb_assert (attr);
+       }
+      if (attr != nullptr)
+       {
+         dwarf2_const_value (attr, sym, cu);
+         attr2 = dwarf2_attr (die, DW_AT_external, cu);
+         if (!suppress_add)
            {
-             /* This is either a Pragma Import or Export.  They can
-                be distinguished by the declaration flag.  */
-             sym->set_linkage_name (physname);
-             if (die_is_declaration (die, cu))
-               {
-                 /* For Import, create a symbol using the source
-                    name, and have it refer to the linkage name.  */
-                 SYMBOL_LOCATION_BATON (sym) = (void *) linkagename;
-                 sym->set_loc_class_index (ada_block_index);
-               }
+             if (attr2 != nullptr && attr2->as_boolean ())
+               list_to_add = &cu->get_builder ()->get_global_symbols ();
              else
-               {
-                 /* For Export, create a symbol using the source
-                    name, then create a second symbol that refers
-                    back to it.  */
-                 add_ada_export_symbol (sym, linkagename, physname, cu,
-                                        *list_to_add);
-               }
+               list_to_add = cu->list_in_scope;
            }
          break;
-       case DW_TAG_inlined_subroutine:
-         /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
-            finish_block.  */
-         sym->set_domain (FUNCTION_DOMAIN);
-         sym->set_loc_class_index (LOC_BLOCK);
-         sym->set_is_inlined (1);
-         list_to_add = cu->list_in_scope;
-         break;
-       case DW_TAG_template_value_param:
-         suppress_add = 1;
-         [[fallthrough]];
-       case DW_TAG_constant:
-       case DW_TAG_variable:
-       case DW_TAG_member:
-         sym->set_domain (VAR_DOMAIN);
-         /* Compilation with minimal debug info may result in
-            variables with missing type entries.  Change the
-            misleading `void' type to something sensible.  */
-         if (sym->type ()->code () == TYPE_CODE_VOID)
-           {
-             type_allocator alloc (objfile, cu->lang ());
-             struct type *int_type
-               = alloc.copy_type (builtin_type (objfile)->builtin_int);
-             sym->set_type (int_type);
-           }
+       }
+      attr = dwarf2_attr (die, DW_AT_location, cu);
+      if (attr != nullptr)
+       {
+         var_decode_location (attr, sym, cu);
+         attr2 = dwarf2_attr (die, DW_AT_external, cu);
 
-         attr = dwarf2_attr (die, DW_AT_const_value, cu);
-         /* In the case of DW_TAG_member, we should only be called for
-            static const members.  */
-         if (die->tag == DW_TAG_member)
-           {
-             /* dwarf2_add_field uses die_is_declaration,
-                so we do the same.  */
-             gdb_assert (die_is_declaration (die, cu));
-             gdb_assert (attr);
-           }
-         if (attr != nullptr)
+         /* Fortran explicitly imports any global symbols to the local
+            scope by DW_TAG_common_block.  */
+         if (cu->lang () == language_fortran && die->parent
+             && die->parent->tag == DW_TAG_common_block)
+           attr2 = nullptr;
+
+         if (sym->loc_class () == LOC_STATIC
+             && sym->value_address () == 0
+             && !per_objfile->per_bfd->has_section_at_zero)
            {
-             dwarf2_const_value (attr, sym, cu);
-             attr2 = dwarf2_attr (die, DW_AT_external, cu);
-             if (!suppress_add)
-               {
-                 if (attr2 != nullptr && attr2->as_boolean ())
-                   list_to_add = &cu->get_builder ()->get_global_symbols ();
-                 else
-                   list_to_add = cu->list_in_scope;
-               }
-             break;
+             /* When a static variable is eliminated by the linker,
+                the corresponding debug information is not stripped
+                out, but the variable address is set to null;
+                do not add such variables into symbol table.  */
            }
-         attr = dwarf2_attr (die, DW_AT_location, cu);
-         if (attr != nullptr)
+         else if (attr2 != nullptr && attr2->as_boolean ())
            {
-             var_decode_location (attr, sym, cu);
-             attr2 = dwarf2_attr (die, DW_AT_external, cu);
-
-             /* Fortran explicitly imports any global symbols to the local
-                scope by DW_TAG_common_block.  */
-             if (cu->lang () == language_fortran && die->parent
-                 && die->parent->tag == DW_TAG_common_block)
-               attr2 = NULL;
-
              if (sym->loc_class () == LOC_STATIC
-                 && sym->value_address () == 0
-                 && !per_objfile->per_bfd->has_section_at_zero)
-               {
-                 /* When a static variable is eliminated by the linker,
-                    the corresponding debug information is not stripped
-                    out, but the variable address is set to null;
-                    do not add such variables into symbol table.  */
-               }
-             else if (attr2 != nullptr && attr2->as_boolean ())
+                 && (objfile->flags & OBJF_MAINLINE) == 0
+                 && per_objfile->per_bfd->can_copy)
                {
-                 if (sym->loc_class () == LOC_STATIC
-                     && (objfile->flags & OBJF_MAINLINE) == 0
-                     && per_objfile->per_bfd->can_copy)
-                   {
-                     /* A global static variable might be subject to
-                        copy relocation.  We first check for a local
-                        minsym, though, because maybe the symbol was
-                        marked hidden, in which case this would not
-                        apply.  */
-                     bound_minimal_symbol found
-                       = (lookup_minimal_symbol_linkage
-                          (sym->linkage_name (), objfile, false));
-                     if (found.minsym != nullptr)
-                       sym->maybe_copied = 1;
-                   }
-
-                 /* A variable with DW_AT_external is never static,
-                    but it may be block-scoped.  */
-                 list_to_add
-                   = ((cu->list_in_scope
-                       == &cu->get_builder ()->get_file_symbols ())
-                      ? &cu->get_builder ()->get_global_symbols ()
-                      : cu->list_in_scope);
+                 /* A global static variable might be subject to
+                    copy relocation.  We first check for a local
+                    minsym, though, because maybe the symbol was
+                    marked hidden, in which case this would not
+                    apply.  */
+                 bound_minimal_symbol found
+                   = (lookup_minimal_symbol_linkage
+                      (sym->linkage_name (), objfile, false));
+                 if (found.minsym != nullptr)
+                   sym->maybe_copied = 1;
                }
-             else
-               list_to_add = cu->list_in_scope;
 
-             if (list_to_add != nullptr
-                 && is_ada_import_or_export (cu, physname, linkagename))
-               {
-                 /* This is a Pragma Export.  A Pragma Import won't
-                    be seen here, because it will not have a location
-                    and so will be handled below.  */
-                 add_ada_export_symbol (sym, physname, linkagename, cu,
-                                        *list_to_add);
-               }
+             /* A variable with DW_AT_external is never static,
+                but it may be block-scoped.  */
+             list_to_add
+               = ((cu->list_in_scope
+                   == &cu->get_builder ()->get_file_symbols ())
+                  ? &cu->get_builder ()->get_global_symbols ()
+                  : cu->list_in_scope);
            }
          else
+           list_to_add = cu->list_in_scope;
+
+         if (list_to_add != nullptr
+             && is_ada_import_or_export (cu, physname, linkagename))
            {
-             /* We do not know the address of this symbol.
-                If it is an external symbol and we have type information
-                for it, enter the symbol as a LOC_UNRESOLVED symbol.
-                The address of the variable will then be determined from
-                the minimal symbol table whenever the variable is
-                referenced.  */
-             attr2 = dwarf2_attr (die, DW_AT_external, cu);
-
-             /* Fortran explicitly imports any global symbols to the local
-                scope by DW_TAG_common_block.  */
-             if (cu->lang () == language_fortran && die->parent
-                 && die->parent->tag == DW_TAG_common_block)
-               {
-                 /* SYMBOL_CLASS doesn't matter here because
-                    read_common_block is going to reset it.  */
-                 if (!suppress_add)
-                   list_to_add = cu->list_in_scope;
-               }
-             else if (is_ada_import_or_export (cu, physname, linkagename))
-               {
-                 /* This is a Pragma Import.  A Pragma Export won't
-                    be seen here, because it will have a location and
-                    so will be handled above.  */
-                 sym->set_linkage_name (physname);
-                 list_to_add
-                   = ((cu->list_in_scope
-                       == &cu->get_builder ()->get_file_symbols ())
-                      ? &cu->get_builder ()->get_global_symbols ()
-                      : cu->list_in_scope);
-                 SYMBOL_LOCATION_BATON (sym) = (void *) linkagename;
-                 sym->set_loc_class_index (ada_imported_index);
-               }
-             else if (attr2 != nullptr && attr2->as_boolean ()
-                      && dwarf2_attr (die, DW_AT_type, cu) != NULL)
-               {
-                 /* A variable with DW_AT_external is never static, but it
-                    may be block-scoped.  */
-                 list_to_add
-                   = ((cu->list_in_scope
-                       == &cu->get_builder ()->get_file_symbols ())
-                      ? &cu->get_builder ()->get_global_symbols ()
-                      : cu->list_in_scope);
-
-                 sym->set_loc_class_index (LOC_UNRESOLVED);
-               }
-             else if (!die_is_declaration (die, cu))
-               {
-                 /* Use the default LOC_OPTIMIZED_OUT class.  */
-                 gdb_assert (sym->loc_class () == LOC_OPTIMIZED_OUT);
-                 if (!suppress_add)
-                   list_to_add = cu->list_in_scope;
-               }
+             /* This is a Pragma Export.  A Pragma Import won't
+                be seen here, because it will not have a location
+                and so will be handled below.  */
+             add_ada_export_symbol (sym, physname, linkagename, cu,
+                                    *list_to_add);
            }
-         break;
-       case DW_TAG_formal_parameter:
-         {
-           /* If we are inside a function, mark this as an argument.  If
-              not, we might be looking at an argument to an inlined function
-              when we do not have enough information to show inlined frames;
-              pretend it's a local variable in that case so that the user can
-              still see it.  */
-           sym->set_domain (VAR_DOMAIN);
-           if (cu->get_builder ()->current_context_has_function ())
-             sym->set_is_argument (true);
-           attr = dwarf2_attr (die, DW_AT_location, cu);
-           if (attr != nullptr)
-             {
-               var_decode_location (attr, sym, cu);
-             }
-           attr = dwarf2_attr (die, DW_AT_const_value, cu);
-           if (attr != nullptr)
-             {
-               dwarf2_const_value (attr, sym, cu);
-             }
+       }
+      else
+       {
+         /* We do not know the address of this symbol.
+            If it is an external symbol and we have type information
+            for it, enter the symbol as a LOC_UNRESOLVED symbol.
+            The address of the variable will then be determined from
+            the minimal symbol table whenever the variable is
+            referenced.  */
+         attr2 = dwarf2_attr (die, DW_AT_external, cu);
 
-           list_to_add = cu->list_in_scope;
-         }
-         break;
-       case DW_TAG_unspecified_parameters:
-         /* From varargs functions; gdb doesn't seem to have any
-            interest in this information, so just ignore it for now.
-            (FIXME?) */
-         break;
-       case DW_TAG_template_type_param:
-         suppress_add = 1;
-         [[fallthrough]];
-       case DW_TAG_class_type:
-       case DW_TAG_interface_type:
-       case DW_TAG_structure_type:
-       case DW_TAG_union_type:
-       case DW_TAG_set_type:
-       case DW_TAG_enumeration_type:
-         if (cu->lang () == language_c
-             || cu->lang () == language_cplus
-             || cu->lang () == language_objc
-             || cu->lang () == language_opencl
-             || cu->lang () == language_minimal)
+         /* Fortran explicitly imports any global symbols to the local
+            scope by DW_TAG_common_block.  */
+         if (cu->lang () == language_fortran && die->parent
+             && die->parent->tag == DW_TAG_common_block)
            {
-             /* These languages have a tag namespace.  Note that
-                there's a special hack for C++ in the matching code,
-                so we don't need to enter a separate typedef for the
-                tag.  */
-             sym->set_loc_class_index (LOC_TYPEDEF);
-             sym->set_domain (STRUCT_DOMAIN);
+             /* SYMBOL_CLASS doesn't matter here because
+                read_common_block is going to reset it.  */
+             if (!suppress_add)
+               list_to_add = cu->list_in_scope;
            }
-         else
+         else if (is_ada_import_or_export (cu, physname, linkagename))
            {
-             /* Other languages don't have a tag namespace.  */
-             sym->set_loc_class_index (LOC_TYPEDEF);
-             sym->set_domain (TYPE_DOMAIN);
+             /* This is a Pragma Import.  A Pragma Export won't
+                be seen here, because it will have a location and
+                so will be handled above.  */
+             sym->set_linkage_name (physname);
+             list_to_add
+               = ((cu->list_in_scope
+                   == &cu->get_builder ()->get_file_symbols ())
+                  ? &cu->get_builder ()->get_global_symbols ()
+                  : cu->list_in_scope);
+             SYMBOL_LOCATION_BATON (sym) = (void *) linkagename;
+             sym->set_loc_class_index (ada_imported_index);
            }
-
-         /* NOTE: carlton/2003-11-10: C++ class symbols shouldn't
-            really ever be static objects: otherwise, if you try
-            to, say, break of a class's method and you're in a file
-            which doesn't mention that class, it won't work unless
-            the check for all static symbols in lookup_symbol_aux
-            saves you.  See the OtherFileClass tests in
-            gdb.c++/namespace.exp.  */
-
-         if (!suppress_add)
+         else if (attr2 != nullptr && attr2->as_boolean ()
+                  && dwarf2_attr (die, DW_AT_type, cu) != nullptr)
            {
-             buildsym_compunit *builder = cu->get_builder ();
+             /* A variable with DW_AT_external is never static, but it
+                may be block-scoped.  */
              list_to_add
-               = ((cu->list_in_scope == &builder->get_file_symbols ()
-                   && cu->lang () == language_cplus)
-                  ? &builder->get_global_symbols ()
+               = ((cu->list_in_scope
+                   == &cu->get_builder ()->get_file_symbols ())
+                  ? &cu->get_builder ()->get_global_symbols ()
                   : cu->list_in_scope);
 
-             /* The semantics of C++ state that "struct foo {
-                ... }" also defines a typedef for "foo".  */
-             if (cu->lang () == language_cplus
-                 || cu->lang () == language_ada
-                 || cu->lang () == language_d
-                 || cu->lang () == language_rust)
-               {
-                 /* The symbol's name is already allocated along
-                    with this objfile, so we don't need to
-                    duplicate it for the type.  */
-                 if (sym->type ()->name () == 0)
-                   sym->type ()->set_name (sym->search_name ());
-               }
+             sym->set_loc_class_index (LOC_UNRESOLVED);
            }
-         break;
-       case DW_TAG_unspecified_type:
-         if (cu->lang () == language_ada)
-           break;
-         [[fallthrough]];
-       case DW_TAG_typedef:
-       case DW_TAG_array_type:
-       case DW_TAG_base_type:
-       case DW_TAG_subrange_type:
-       case DW_TAG_generic_subrange:
-         sym->set_loc_class_index (LOC_TYPEDEF);
-         sym->set_domain (TYPE_DOMAIN);
-         list_to_add = cu->list_in_scope;
-         break;
-       case DW_TAG_enumerator:
-         sym->set_domain (VAR_DOMAIN);
-         attr = dwarf2_attr (die, DW_AT_const_value, cu);
-         if (attr != nullptr)
+         else if (!die_is_declaration (die, cu))
            {
-             dwarf2_const_value (attr, sym, cu);
+             /* Use the default LOC_OPTIMIZED_OUT class.  */
+             gdb_assert (sym->loc_class () == LOC_OPTIMIZED_OUT);
+             if (!suppress_add)
+               list_to_add = cu->list_in_scope;
            }
+       }
+      break;
+    case DW_TAG_formal_parameter:
+      {
+       /* If we are inside a function, mark this as an argument.  If
+          not, we might be looking at an argument to an inlined function
+          when we do not have enough information to show inlined frames;
+          pretend it's a local variable in that case so that the user can
+          still see it.  */
+       sym->set_domain (VAR_DOMAIN);
+       if (cu->get_builder ()->current_context_has_function ())
+         sym->set_is_argument (true);
+       attr = dwarf2_attr (die, DW_AT_location, cu);
+       if (attr != nullptr)
+         var_decode_location (attr, sym, cu);
+       attr = dwarf2_attr (die, DW_AT_const_value, cu);
+       if (attr != nullptr)
+         dwarf2_const_value (attr, sym, cu);
+
+       list_to_add = cu->list_in_scope;
+      }
+      break;
+    case DW_TAG_unspecified_parameters:
+      /* From varargs functions; gdb doesn't seem to have any
+        interest in this information, so just ignore it for now.
+        (FIXME?) */
+      break;
+    case DW_TAG_template_type_param:
+      suppress_add = true;
+      [[fallthrough]];
+    case DW_TAG_class_type:
+    case DW_TAG_interface_type:
+    case DW_TAG_structure_type:
+    case DW_TAG_union_type:
+    case DW_TAG_set_type:
+    case DW_TAG_enumeration_type:
+      if (cu->lang () == language_c
+         || cu->lang () == language_cplus
+         || cu->lang () == language_objc
+         || cu->lang () == language_opencl
+         || cu->lang () == language_minimal)
+       {
+         /* These languages have a tag namespace.  Note that
+            there's a special hack for C++ in the matching code,
+            so we don't need to enter a separate typedef for the
+            tag.  */
+         sym->set_loc_class_index (LOC_TYPEDEF);
+         sym->set_domain (STRUCT_DOMAIN);
+       }
+      else
+       {
+         /* Other languages don't have a tag namespace.  */
+         sym->set_loc_class_index (LOC_TYPEDEF);
+         sym->set_domain (TYPE_DOMAIN);
+       }
 
-         /* NOTE: carlton/2003-11-10: See comment above in the
-            DW_TAG_class_type, etc. block.  */
+      /* NOTE: carlton/2003-11-10: C++ class symbols shouldn't
+        really ever be static objects: otherwise, if you try
+        to, say, break of a class's method and you're in a file
+        which doesn't mention that class, it won't work unless
+        the check for all static symbols in lookup_symbol_aux
+        saves you.  See the OtherFileClass tests in
+        gdb.c++/namespace.exp.  */
 
+      if (!suppress_add)
+       {
+         buildsym_compunit *builder = cu->get_builder ();
          list_to_add
-           = ((cu->list_in_scope == &cu->get_builder ()->get_file_symbols ()
+           = ((cu->list_in_scope == &builder->get_file_symbols ()
                && cu->lang () == language_cplus)
-              ? &cu->get_builder ()->get_global_symbols ()
+              ? &builder->get_global_symbols ()
               : cu->list_in_scope);
-         break;
-       case DW_TAG_imported_declaration:
-       case DW_TAG_namespace:
-         sym->set_domain (TYPE_DOMAIN);
-         sym->set_loc_class_index (LOC_TYPEDEF);
-         list_to_add = &cu->get_builder ()->get_global_symbols ();
-         break;
-       case DW_TAG_module:
-         sym->set_loc_class_index (LOC_TYPEDEF);
-         sym->set_domain (MODULE_DOMAIN);
-         list_to_add = &cu->get_builder ()->get_global_symbols ();
-         break;
-       case DW_TAG_common_block:
-         sym->set_loc_class_index (LOC_COMMON_BLOCK);
-         sym->set_domain (COMMON_BLOCK_DOMAIN);
-         list_to_add = cu->list_in_scope;
-         break;
-       case DW_TAG_namelist:
-         sym->set_loc_class_index (LOC_STATIC);
-         sym->set_domain (VAR_DOMAIN);
-         list_to_add = cu->list_in_scope;
-         break;
-       default:
-         /* Not a tag we recognize.  Hopefully we aren't processing
-            trash data, but since we must specifically ignore things
-            we don't recognize, there is nothing else we should do at
-            this point.  */
-         complaint (_("unsupported tag: '%s'"),
-                    dwarf_tag_name (die->tag));
-         break;
-       }
 
-      if (suppress_add)
-       {
-         sym->hash_next = objfile->template_symbols;
-         objfile->template_symbols = sym;
-         list_to_add = NULL;
+         /* The semantics of C++ state that "struct foo {
+            ... }" also defines a typedef for "foo".  */
+         if (cu->lang () == language_cplus
+             || cu->lang () == language_ada
+             || cu->lang () == language_d
+             || cu->lang () == language_rust)
+           {
+             /* The symbol's name is already allocated along
+                with this objfile, so we don't need to
+                duplicate it for the type.  */
+             if (sym->type ()->name () == 0)
+               sym->type ()->set_name (sym->search_name ());
+           }
        }
+      break;
+    case DW_TAG_unspecified_type:
+      if (cu->lang () == language_ada)
+       break;
+      [[fallthrough]];
+    case DW_TAG_typedef:
+    case DW_TAG_array_type:
+    case DW_TAG_base_type:
+    case DW_TAG_subrange_type:
+    case DW_TAG_generic_subrange:
+      sym->set_loc_class_index (LOC_TYPEDEF);
+      sym->set_domain (TYPE_DOMAIN);
+      list_to_add = cu->list_in_scope;
+      break;
+    case DW_TAG_enumerator:
+      sym->set_domain (VAR_DOMAIN);
+      attr = dwarf2_attr (die, DW_AT_const_value, cu);
+      if (attr != nullptr)
+       dwarf2_const_value (attr, sym, cu);
 
-      if (list_to_add != NULL)
-       add_symbol_to_list (sym, *list_to_add);
+      /* NOTE: carlton/2003-11-10: See comment above in the
+        DW_TAG_class_type, etc. block.  */
+
+      list_to_add
+       = ((cu->list_in_scope == &cu->get_builder ()->get_file_symbols ()
+           && cu->lang () == language_cplus)
+          ? &cu->get_builder ()->get_global_symbols ()
+          : cu->list_in_scope);
+      break;
+    case DW_TAG_imported_declaration:
+    case DW_TAG_namespace:
+      sym->set_domain (TYPE_DOMAIN);
+      sym->set_loc_class_index (LOC_TYPEDEF);
+      list_to_add = &cu->get_builder ()->get_global_symbols ();
+      break;
+    case DW_TAG_module:
+      sym->set_loc_class_index (LOC_TYPEDEF);
+      sym->set_domain (MODULE_DOMAIN);
+      list_to_add = &cu->get_builder ()->get_global_symbols ();
+      break;
+    case DW_TAG_common_block:
+      sym->set_loc_class_index (LOC_COMMON_BLOCK);
+      sym->set_domain (COMMON_BLOCK_DOMAIN);
+      list_to_add = cu->list_in_scope;
+      break;
+    case DW_TAG_namelist:
+      sym->set_loc_class_index (LOC_STATIC);
+      sym->set_domain (VAR_DOMAIN);
+      list_to_add = cu->list_in_scope;
+      break;
+    default:
+      /* Not a tag we recognize.  Hopefully we aren't processing
+        trash data, but since we must specifically ignore things
+        we don't recognize, there is nothing else we should do at
+        this point.  */
+      complaint (_("unsupported tag: '%s'"),
+                dwarf_tag_name (die->tag));
+      break;
+    }
 
-      /* For the benefit of old versions of GCC, check for anonymous
-        namespaces based on the demangled name.  */
-      if (!cu->processing_has_namespace_info
-         && cu->lang () == language_cplus)
-       cp_scan_for_anonymous_namespaces (cu->get_builder (), sym, objfile);
+  if (suppress_add)
+    {
+      sym->hash_next = objfile->template_symbols;
+      objfile->template_symbols = sym;
+      return;
     }
-  return (sym);
+
+  if (list_to_add != nullptr)
+    add_symbol_to_list (sym, *list_to_add);
+}
+
+/* Given a pointer to a DWARF information entry, figure out if we need
+   to make a symbol table entry for it, and if so, create a new entry
+   and return a pointer to it.
+   If TYPE is nullptr, determine symbol type from the die, otherwise
+   used the passed type.
+   If SPACE is not nullptr, use it to hold the new symbol.  If it is
+   nullptr, allocate a new symbol on the objfile's obstack.  */
+
+static struct symbol *
+new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
+           struct symbol *space)
+{
+  dwarf2_per_objfile *per_objfile = cu->per_objfile;
+  struct objfile *objfile = per_objfile->objfile;
+
+  const char *name = dwarf2_name (die, cu);
+  if (name == nullptr && (die->tag == DW_TAG_subprogram
+                         || die->tag == DW_TAG_inlined_subroutine
+                         || die->tag == DW_TAG_entry_point))
+    name = dw2_linkage_name (die, cu);
+  if (name == nullptr)
+    return nullptr;
+
+  struct symbol *sym = space;
+  if (sym == nullptr)
+    sym = objfile->new_symbol<symbol> ();
+
+  sym->set_language (cu->lang (), &objfile->objfile_obstack);
+
+  /* Fortran does not have mangling standard and the mangling does differ
+     between gfortran, iFort etc.  */
+  const char *physname
+    = ((cu->lang () == language_fortran || cu->lang () == language_ada)
+       ? dwarf2_full_name (name, die, cu)
+       : dwarf2_physname (name, die, cu));
+  const char *linkagename = dw2_linkage_name (die, cu);
+
+  /* Cache this symbol's name and the name's demangled form (if any).  */
+  sym->set_linkage_name (linkagename != nullptr
+                        ? linkagename
+                        : physname);
+  if (linkagename != nullptr && cu->lang () != language_ada)
+    sym->set_demangled_name (physname == linkagename
+                            ? name
+                            : physname,
+                            &objfile->objfile_obstack);
+
+  /* Handle DW_AT_artificial.  */
+  struct attribute *attr = dwarf2_attr (die, DW_AT_artificial, cu);
+  if (attr != nullptr)
+    sym->set_is_artificial (attr->as_boolean ());
+
+  /* Default assumptions.
+     Use the passed type or decode it from the die.  */
+  sym->set_domain (UNDEF_DOMAIN);
+  sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
+  sym->set_type (type != nullptr
+                ? type
+                : die_type (die, cu));
+
+  /* Handle DW_AT_{call,decl}_{file,line}.  */
+  new_symbol_file_line (die, cu, sym);
+
+  /* Handle TAG-specific part.  */
+  new_symbol (die, cu, sym, linkagename, physname);
+
+  /* For the benefit of old versions of GCC, check for anonymous
+     namespaces based on the demangled name.  */
+  if (!cu->processing_has_namespace_info
+      && cu->lang () == language_cplus)
+    cp_scan_for_anonymous_namespaces (cu->get_builder (), sym, objfile);
+
+  return sym;
 }
 
 /* Read a constant value from an attribute.  Either set *VALUE, or if