]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Move cooked_index_entry to new files
authorTom Tromey <tom@tromey.com>
Mon, 24 Mar 2025 21:11:02 +0000 (15:11 -0600)
committerTom Tromey <tom@tromey.com>
Tue, 1 Apr 2025 13:30:10 +0000 (07:30 -0600)
This moves cooked_index_entry and some related helper code to a couple
of new files, dwarf2/cooked-index-entry.[ch].

The main rationale for this is that in order to finish this series and
remove "cooked_index_worker::result_type", I had to split
cooked-index.h into multiple parts to avoid circular includes.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
gdb/Makefile.in
gdb/dwarf2/cooked-index-entry.c [new file with mode: 0644]
gdb/dwarf2/cooked-index-entry.h [new file with mode: 0644]
gdb/dwarf2/cooked-index.c
gdb/dwarf2/cooked-index.h

index 5329af31e739cfaca2da3ef2f8f22edf5ed00ad7..b4e54071eedbbc3d0c7400c1454cf76d3b86ee89 100644 (file)
@@ -1097,6 +1097,7 @@ COMMON_SFILES = \
        dwarf2/attribute.c \
        dwarf2/comp-unit-head.c \
        dwarf2/cooked-index.c \
+       dwarf2/cooked-index-entry.c \
        dwarf2/cooked-index-worker.c \
        dwarf2/cooked-indexer.c \
        dwarf2/cu.c \
@@ -1356,6 +1357,7 @@ HFILES_NO_SRCDIR = \
        dummy-frame.h \
        dwarf2/aranges.h \
        dwarf2/cooked-index.h \
+       dwarf2/cooked-index-entry.h \
        dwarf2/cooked-index-worker.h \
        dwarf2/cooked-indexer.h \
        dwarf2/cu.h \
diff --git a/gdb/dwarf2/cooked-index-entry.c b/gdb/dwarf2/cooked-index-entry.c
new file mode 100644 (file)
index 0000000..197f62a
--- /dev/null
@@ -0,0 +1,242 @@
+/* Entry in the cooked index
+
+   Copyright (C) 2022-2024 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "dwarf2/cooked-index-entry.h"
+#include "dwarf2/tag.h"
+#include "gdbsupport/gdb-safe-ctype.h"
+#include "gdbsupport/selftest.h"
+
+/* See cooked-index.h.  */
+
+std::string
+to_string (cooked_index_flag flags)
+{
+  static constexpr cooked_index_flag::string_mapping mapping[] = {
+    MAP_ENUM_FLAG (IS_MAIN),
+    MAP_ENUM_FLAG (IS_STATIC),
+    MAP_ENUM_FLAG (IS_LINKAGE),
+    MAP_ENUM_FLAG (IS_TYPE_DECLARATION),
+    MAP_ENUM_FLAG (IS_PARENT_DEFERRED),
+  };
+
+  return flags.to_string (mapping);
+}
+
+/* See cooked-index.h.  */
+
+int
+cooked_index_entry::compare (const char *stra, const char *strb,
+                            comparison_mode mode)
+{
+#if defined (__GNUC__) && !defined (__clang__) && __GNUC__ <= 7
+  /* Work around error with gcc 7.5.0.  */
+  auto munge = [] (char c) -> unsigned char
+#else
+  auto munge = [] (char c) constexpr -> unsigned char
+#endif
+    {
+      /* Treat '<' as if it ended the string.  This lets something
+        like "func<t>" match "func<t<int>>".  See the "Breakpoints in
+        template functions" section in the manual.  */
+      if (c == '<')
+       return '\0';
+      return TOLOWER ((unsigned char) c);
+    };
+
+  unsigned char a = munge (*stra);
+  unsigned char b = munge (*strb);
+
+  while (a != '\0' && b != '\0' && a == b)
+    {
+      a = munge (*++stra);
+      b = munge (*++strb);
+    }
+
+  if (a == b)
+    return 0;
+
+  /* When completing, if STRB ends earlier than STRA, consider them as
+     equal.  */
+  if (mode == COMPLETE && b == '\0')
+    return 0;
+
+  return a < b ? -1 : 1;
+}
+
+#if GDB_SELF_TEST
+
+namespace {
+
+void
+test_compare ()
+{
+  /* Convenience aliases.  */
+  const auto mode_compare = cooked_index_entry::MATCH;
+  const auto mode_sort = cooked_index_entry::SORT;
+  const auto mode_complete = cooked_index_entry::COMPLETE;
+
+  SELF_CHECK (cooked_index_entry::compare ("abcd", "abcd",
+                                          mode_compare) == 0);
+  SELF_CHECK (cooked_index_entry::compare ("abcd", "abcd",
+                                          mode_complete) == 0);
+
+  SELF_CHECK (cooked_index_entry::compare ("abcd", "ABCDE",
+                                          mode_compare) < 0);
+  SELF_CHECK (cooked_index_entry::compare ("ABCDE", "abcd",
+                                          mode_compare) > 0);
+  SELF_CHECK (cooked_index_entry::compare ("abcd", "ABCDE",
+                                          mode_complete) < 0);
+  SELF_CHECK (cooked_index_entry::compare ("ABCDE", "abcd",
+                                          mode_complete) == 0);
+
+  SELF_CHECK (cooked_index_entry::compare ("name", "name<>",
+                                          mode_compare) == 0);
+  SELF_CHECK (cooked_index_entry::compare ("name<>", "name",
+                                          mode_compare) == 0);
+  SELF_CHECK (cooked_index_entry::compare ("name", "name<>",
+                                          mode_complete) == 0);
+  SELF_CHECK (cooked_index_entry::compare ("name<>", "name",
+                                          mode_complete) == 0);
+
+  SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<arg>",
+                                          mode_compare) == 0);
+  SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<ag>",
+                                          mode_compare) == 0);
+  SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<arg>",
+                                          mode_complete) == 0);
+  SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<ag>",
+                                          mode_complete) == 0);
+
+  SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>",
+                                          "name<arg<more>>",
+                                          mode_compare) == 0);
+  SELF_CHECK (cooked_index_entry::compare ("name<arg>",
+                                          "name<arg<more>>",
+                                          mode_compare) == 0);
+
+  SELF_CHECK (cooked_index_entry::compare ("name", "name<arg<more>>",
+                                          mode_compare) == 0);
+  SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>", "name",
+                                          mode_compare) == 0);
+  SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>", "name<arg<",
+                                          mode_compare) == 0);
+  SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>", "name<arg<",
+                                          mode_complete) == 0);
+
+  SELF_CHECK (cooked_index_entry::compare ("", "abcd", mode_compare) < 0);
+  SELF_CHECK (cooked_index_entry::compare ("", "abcd", mode_complete) < 0);
+  SELF_CHECK (cooked_index_entry::compare ("abcd", "", mode_compare) > 0);
+  SELF_CHECK (cooked_index_entry::compare ("abcd", "", mode_complete) == 0);
+
+  SELF_CHECK (cooked_index_entry::compare ("func", "func<type>",
+                                          mode_sort) == 0);
+  SELF_CHECK (cooked_index_entry::compare ("func<type>", "func1",
+                                          mode_sort) < 0);
+}
+
+} /* anonymous namespace */
+
+#endif /* GDB_SELF_TEST */
+
+/* See cooked-index.h.  */
+
+bool
+cooked_index_entry::matches (domain_search_flags kind) const
+{
+  /* Just reject type declarations.  */
+  if ((flags & IS_TYPE_DECLARATION) != 0)
+    return false;
+
+  return tag_matches_domain (tag, kind, lang);
+}
+
+/* See cooked-index.h.  */
+
+const char *
+cooked_index_entry::full_name (struct obstack *storage,
+                              cooked_index_full_name_flag name_flags,
+                              const char *default_sep) const
+{
+  const char *local_name = ((name_flags & FOR_MAIN) != 0) ? name : canonical;
+
+  if ((flags & IS_LINKAGE) != 0 || get_parent () == nullptr)
+    return local_name;
+
+  const char *sep = default_sep;
+  switch (lang)
+    {
+    case language_cplus:
+    case language_rust:
+    case language_fortran:
+      sep = "::";
+      break;
+
+    case language_ada:
+      if ((name_flags & FOR_ADA_LINKAGE_NAME) != 0)
+       {
+         sep = "__";
+         break;
+       }
+      [[fallthrough]];
+    case language_go:
+    case language_d:
+      sep = ".";
+      break;
+
+    default:
+      if (sep == nullptr)
+       return local_name;
+      break;
+    }
+
+  /* The FOR_ADA_LINKAGE_NAME flag should only affect Ada entries, so
+     disable it here if we don't need it.  */
+  if (lang != language_ada)
+    name_flags &= ~FOR_ADA_LINKAGE_NAME;
+
+  get_parent ()->write_scope (storage, sep, name_flags);
+  obstack_grow0 (storage, local_name, strlen (local_name));
+  return (const char *) obstack_finish (storage);
+}
+
+/* See cooked-index.h.  */
+
+void
+cooked_index_entry::write_scope (struct obstack *storage,
+                                const char *sep,
+                                cooked_index_full_name_flag flags) const
+{
+  if (get_parent () != nullptr)
+    get_parent ()->write_scope (storage, sep, flags);
+  /* When computing the Ada linkage name, the entry might not have
+     been canonicalized yet, so use the 'name'.  */
+  const char *local_name = ((flags & (FOR_MAIN | FOR_ADA_LINKAGE_NAME)) != 0
+                           ? name
+                           : canonical);
+  obstack_grow (storage, local_name, strlen (local_name));
+  obstack_grow (storage, sep, strlen (sep));
+}
+
+void _initialize_dwarf2_entry ();
+void _initialize_dwarf2_entry ()
+{
+#if GDB_SELF_TEST
+  selftests::register_test ("cooked_index_entry::compare", test_compare);
+#endif
+}
diff --git a/gdb/dwarf2/cooked-index-entry.h b/gdb/dwarf2/cooked-index-entry.h
new file mode 100644 (file)
index 0000000..bb47e32
--- /dev/null
@@ -0,0 +1,258 @@
+/* Entry in the cooked index
+
+   Copyright (C) 2022-2024 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GDB_DWARF2_COOKED_INDEX_ENTRY_H
+#define GDB_DWARF2_COOKED_INDEX_ENTRY_H
+
+#include "dwarf2/parent-map.h"
+#include "dwarf2/types.h"
+#include "symtab.h"
+#include "gdbsupport/gdb_obstack.h"
+#include "quick-symbol.h"
+
+/* Flags that describe an entry in the index.  */
+enum cooked_index_flag_enum : unsigned char
+{
+  /* True if this entry is the program's "main".  */
+  IS_MAIN = 1,
+  /* True if this entry represents a "static" object.  */
+  IS_STATIC = 2,
+  /* True if this entry uses the linkage name.  */
+  IS_LINKAGE = 4,
+  /* True if this entry is just for the declaration of a type, not the
+     definition.  */
+  IS_TYPE_DECLARATION = 8,
+  /* True is parent_entry.deferred has a value rather than parent_entry
+     .resolved.  */
+  IS_PARENT_DEFERRED = 16,
+  /* True if this entry was synthesized by gdb (as opposed to coming
+     directly from the DWARF).  */
+  IS_SYNTHESIZED = 32,
+};
+DEF_ENUM_FLAGS_TYPE (enum cooked_index_flag_enum, cooked_index_flag);
+
+/* Flags used when requesting the full name of an entry.  */
+enum cooked_index_full_name_enum : unsigned char
+{
+  /* Set when requesting the name of "main".  See the method for the
+     full description.  */
+  FOR_MAIN = 1,
+  /* Set when requesting the linkage name for an Ada entry.  */
+  FOR_ADA_LINKAGE_NAME = 2,
+};
+DEF_ENUM_FLAGS_TYPE (enum cooked_index_full_name_enum, cooked_index_full_name_flag);
+
+/* Type representing either a resolved or deferred cooked_index_entry.  */
+
+union cooked_index_entry_ref
+{
+  cooked_index_entry_ref (parent_map::addr_type deferred_)
+  {
+    deferred = deferred_;
+  }
+
+  cooked_index_entry_ref (const cooked_index_entry *resolved_)
+  {
+    resolved = resolved_;
+  }
+
+  const cooked_index_entry *resolved;
+  parent_map::addr_type deferred;
+};
+
+/* Return a string representation of FLAGS.  */
+
+std::string to_string (cooked_index_flag flags);
+
+/* A cooked_index_entry represents a single item in the index.  Note
+   that two entries can be created for the same DIE -- one using the
+   name, and another one using the linkage name, if any.
+
+   This is an "open" class and the members are all directly
+   accessible.  It is read-only after the index has been fully read
+   and processed.  */
+struct cooked_index_entry : public allocate_on_obstack<cooked_index_entry>
+{
+  cooked_index_entry (sect_offset die_offset_, enum dwarf_tag tag_,
+                     cooked_index_flag flags_,
+                     enum language lang_, const char *name_,
+                     cooked_index_entry_ref parent_entry_,
+                     dwarf2_per_cu *per_cu_)
+    : name (name_),
+      tag (tag_),
+      flags (flags_),
+      lang (lang_),
+      die_offset (die_offset_),
+      per_cu (per_cu_),
+      m_parent_entry (parent_entry_)
+  {
+  }
+
+  /* Return true if this entry matches SEARCH_FLAGS.  */
+  bool matches (block_search_flags search_flags) const
+  {
+    /* Just reject type declarations.  */
+    if ((flags & IS_TYPE_DECLARATION) != 0)
+      return false;
+
+    if ((search_flags & SEARCH_STATIC_BLOCK) != 0
+       && (flags & IS_STATIC) != 0)
+      return true;
+    if ((search_flags & SEARCH_GLOBAL_BLOCK) != 0
+       && (flags & IS_STATIC) == 0)
+      return true;
+    return false;
+  }
+
+  /* Return true if this entry matches KIND.  */
+  bool matches (domain_search_flags kind) const;
+
+  /* Construct the fully-qualified name of this entry and return a
+     pointer to it.  If allocation is needed, it will be done on
+     STORAGE.
+
+     FLAGS affects the result.  If the FOR_MAIN flag is set, we are
+     computing the name of the "main" entry -- one marked
+     DW_AT_main_subprogram.  This matters for avoiding name
+     canonicalization and also a related race (if "main" computation
+     is done during finalization).
+
+     If the FOR_ADA_LINKAGE_NAME flag is set, then Ada-language
+     symbols will have their "linkage-style" name computed.  The
+     default is source-style.
+
+     If the language doesn't prescribe a separator, one can be
+     specified using DEFAULT_SEP.  */
+  const char *full_name (struct obstack *storage,
+                        cooked_index_full_name_flag name_flags = 0,
+                        const char *default_sep = nullptr) const;
+
+  /* Comparison modes for the 'compare' function.  See the function
+     for a description.  */
+  enum comparison_mode
+  {
+    MATCH,
+    SORT,
+    COMPLETE,
+  };
+
+  /* Compare two strings, case-insensitively.  Return -1 if STRA is
+     less than STRB, 0 if they are equal, and 1 if STRA is greater.
+
+     When comparing, '<' is considered to be less than all other
+     printable characters.  This ensures that "t<x>" sorts before
+     "t1", which is necessary when looking up "t".  This '<' handling
+     is to ensure that certain C++ lookups work correctly.  It is
+     inexact, and applied regardless of the search language, but this
+     is ok because callers of this code do more precise filtering
+     according to their needs.  This is also why using a
+     case-insensitive comparison works even for languages that are
+     case sensitive.
+
+     MODE controls how the comparison proceeds.
+
+     MODE==SORT is used when sorting and the only special '<' handling
+     that it does is to ensure that '<' sorts before all other
+     printable characters.  This ensures that the resulting ordering
+     will be binary-searchable.
+
+     MODE==MATCH is used when searching for a symbol.  In this case,
+     STRB must always be the search name, and STRA must be the name in
+     the index that is under consideration.  In compare mode, early
+     termination of STRB may match STRA -- for example, "t<int>" and
+     "t" will be considered to be equal.  (However, if A=="t" and
+     B=="t<int>", then this will not consider them as equal.)
+
+     MODE==COMPLETE is used when searching for a symbol for
+     completion.  In this case, STRB must always be the search name,
+     and STRA must be the name in the index that is under
+     consideration.  In completion mode, early termination of STRB
+     always results in a match.  */
+  static int compare (const char *stra, const char *strb,
+                     comparison_mode mode);
+
+  /* Compare two entries by canonical name.  */
+  bool operator< (const cooked_index_entry &other) const
+  {
+    return compare (canonical, other.canonical, SORT) < 0;
+  }
+
+  /* Set parent entry to PARENT.  */
+  void set_parent (const cooked_index_entry *parent)
+  {
+    gdb_assert ((flags & IS_PARENT_DEFERRED) == 0);
+    m_parent_entry.resolved = parent;
+  }
+
+  /* Resolve deferred parent entry to PARENT.  */
+  void resolve_parent (const cooked_index_entry *parent)
+  {
+    gdb_assert ((flags & IS_PARENT_DEFERRED) != 0);
+    flags = flags & ~IS_PARENT_DEFERRED;
+    m_parent_entry.resolved = parent;
+  }
+
+  /* Return parent entry.  */
+  const cooked_index_entry *get_parent () const
+  {
+    gdb_assert ((flags & IS_PARENT_DEFERRED) == 0);
+    return m_parent_entry.resolved;
+  }
+
+  /* Return deferred parent entry.  */
+  parent_map::addr_type get_deferred_parent () const
+  {
+    gdb_assert ((flags & IS_PARENT_DEFERRED) != 0);
+    return m_parent_entry.deferred;
+  }
+
+  /* The name as it appears in DWARF.  This always points into one of
+     the mapped DWARF sections.  Note that this may be the name or the
+     linkage name -- two entries are created for DIEs which have both
+     attributes.  */
+  const char *name;
+  /* The canonical name.  This may be equal to NAME.  */
+  const char *canonical = nullptr;
+  /* The DWARF tag.  */
+  enum dwarf_tag tag;
+  /* Any flags attached to this entry.  */
+  cooked_index_flag flags;
+  /* The language of this symbol.  */
+  ENUM_BITFIELD (language) lang : LANGUAGE_BITS;
+  /* The offset of this DIE.  */
+  sect_offset die_offset;
+  /* The CU from which this entry originates.  */
+  dwarf2_per_cu *per_cu;
+
+private:
+
+  /* A helper method for full_name.  Emits the full scope of this
+     object, followed by the separator, to STORAGE.  If this entry has
+     a parent, its write_scope method is called first.  See full_name
+     for a description of the FLAGS parameter.  */
+  void write_scope (struct obstack *storage, const char *sep,
+                   cooked_index_full_name_flag flags) const;
+
+  /* The parent entry.  This is NULL for top-level entries.
+     Otherwise, it points to the parent entry, such as a namespace or
+     class.  */
+  cooked_index_entry_ref m_parent_entry;
+};
+
+#endif /* GDB_DWARF2_COOKED_INDEX_ENTRY_H */
index 32e299ffd10c855a3fe5c4fc8ef0bcde4e5c49ce..9d5f152045bd9a28b0c6278f5b4720cb55b69112 100644 (file)
@@ -32,8 +32,6 @@
 #include "observable.h"
 #include "run-on-main-thread.h"
 #include <algorithm>
-#include "gdbsupport/gdb-safe-ctype.h"
-#include "gdbsupport/selftest.h"
 #include "gdbsupport/task-group.h"
 #include "gdbsupport/thread-pool.h"
 #include <chrono>
    here, and then these are all waited for before exit proceeds.  */
 static gdb::unordered_set<cooked_index *> active_vectors;
 
-/* See cooked-index.h.  */
-
-std::string
-to_string (cooked_index_flag flags)
-{
-  static constexpr cooked_index_flag::string_mapping mapping[] = {
-    MAP_ENUM_FLAG (IS_MAIN),
-    MAP_ENUM_FLAG (IS_STATIC),
-    MAP_ENUM_FLAG (IS_LINKAGE),
-    MAP_ENUM_FLAG (IS_TYPE_DECLARATION),
-    MAP_ENUM_FLAG (IS_PARENT_DEFERRED),
-  };
-
-  return flags.to_string (mapping);
-}
-
 /* Return true if LANG requires canonicalization.  This is used
    primarily to work around an issue computing the name of "main".
    This function must be kept in sync with
@@ -92,201 +74,6 @@ language_may_use_plain_main (enum language lang)
 
 /* See cooked-index.h.  */
 
-int
-cooked_index_entry::compare (const char *stra, const char *strb,
-                            comparison_mode mode)
-{
-#if defined (__GNUC__) && !defined (__clang__) && __GNUC__ <= 7
-  /* Work around error with gcc 7.5.0.  */
-  auto munge = [] (char c) -> unsigned char
-#else
-  auto munge = [] (char c) constexpr -> unsigned char
-#endif
-    {
-      /* Treat '<' as if it ended the string.  This lets something
-        like "func<t>" match "func<t<int>>".  See the "Breakpoints in
-        template functions" section in the manual.  */
-      if (c == '<')
-       return '\0';
-      return TOLOWER ((unsigned char) c);
-    };
-
-  unsigned char a = munge (*stra);
-  unsigned char b = munge (*strb);
-
-  while (a != '\0' && b != '\0' && a == b)
-    {
-      a = munge (*++stra);
-      b = munge (*++strb);
-    }
-
-  if (a == b)
-    return 0;
-
-  /* When completing, if STRB ends earlier than STRA, consider them as
-     equal.  */
-  if (mode == COMPLETE && b == '\0')
-    return 0;
-
-  return a < b ? -1 : 1;
-}
-
-#if GDB_SELF_TEST
-
-namespace {
-
-void
-test_compare ()
-{
-  /* Convenience aliases.  */
-  const auto mode_compare = cooked_index_entry::MATCH;
-  const auto mode_sort = cooked_index_entry::SORT;
-  const auto mode_complete = cooked_index_entry::COMPLETE;
-
-  SELF_CHECK (cooked_index_entry::compare ("abcd", "abcd",
-                                          mode_compare) == 0);
-  SELF_CHECK (cooked_index_entry::compare ("abcd", "abcd",
-                                          mode_complete) == 0);
-
-  SELF_CHECK (cooked_index_entry::compare ("abcd", "ABCDE",
-                                          mode_compare) < 0);
-  SELF_CHECK (cooked_index_entry::compare ("ABCDE", "abcd",
-                                          mode_compare) > 0);
-  SELF_CHECK (cooked_index_entry::compare ("abcd", "ABCDE",
-                                          mode_complete) < 0);
-  SELF_CHECK (cooked_index_entry::compare ("ABCDE", "abcd",
-                                          mode_complete) == 0);
-
-  SELF_CHECK (cooked_index_entry::compare ("name", "name<>",
-                                          mode_compare) == 0);
-  SELF_CHECK (cooked_index_entry::compare ("name<>", "name",
-                                          mode_compare) == 0);
-  SELF_CHECK (cooked_index_entry::compare ("name", "name<>",
-                                          mode_complete) == 0);
-  SELF_CHECK (cooked_index_entry::compare ("name<>", "name",
-                                          mode_complete) == 0);
-
-  SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<arg>",
-                                          mode_compare) == 0);
-  SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<ag>",
-                                          mode_compare) == 0);
-  SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<arg>",
-                                          mode_complete) == 0);
-  SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<ag>",
-                                          mode_complete) == 0);
-
-  SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>",
-                                          "name<arg<more>>",
-                                          mode_compare) == 0);
-  SELF_CHECK (cooked_index_entry::compare ("name<arg>",
-                                          "name<arg<more>>",
-                                          mode_compare) == 0);
-
-  SELF_CHECK (cooked_index_entry::compare ("name", "name<arg<more>>",
-                                          mode_compare) == 0);
-  SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>", "name",
-                                          mode_compare) == 0);
-  SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>", "name<arg<",
-                                          mode_compare) == 0);
-  SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>", "name<arg<",
-                                          mode_complete) == 0);
-
-  SELF_CHECK (cooked_index_entry::compare ("", "abcd", mode_compare) < 0);
-  SELF_CHECK (cooked_index_entry::compare ("", "abcd", mode_complete) < 0);
-  SELF_CHECK (cooked_index_entry::compare ("abcd", "", mode_compare) > 0);
-  SELF_CHECK (cooked_index_entry::compare ("abcd", "", mode_complete) == 0);
-
-  SELF_CHECK (cooked_index_entry::compare ("func", "func<type>",
-                                          mode_sort) == 0);
-  SELF_CHECK (cooked_index_entry::compare ("func<type>", "func1",
-                                          mode_sort) < 0);
-}
-
-} /* anonymous namespace */
-
-#endif /* GDB_SELF_TEST */
-
-/* See cooked-index.h.  */
-
-bool
-cooked_index_entry::matches (domain_search_flags kind) const
-{
-  /* Just reject type declarations.  */
-  if ((flags & IS_TYPE_DECLARATION) != 0)
-    return false;
-
-  return tag_matches_domain (tag, kind, lang);
-}
-
-/* See cooked-index.h.  */
-
-const char *
-cooked_index_entry::full_name (struct obstack *storage,
-                              cooked_index_full_name_flag name_flags,
-                              const char *default_sep) const
-{
-  const char *local_name = ((name_flags & FOR_MAIN) != 0) ? name : canonical;
-
-  if ((flags & IS_LINKAGE) != 0 || get_parent () == nullptr)
-    return local_name;
-
-  const char *sep = default_sep;
-  switch (lang)
-    {
-    case language_cplus:
-    case language_rust:
-    case language_fortran:
-      sep = "::";
-      break;
-
-    case language_ada:
-      if ((name_flags & FOR_ADA_LINKAGE_NAME) != 0)
-       {
-         sep = "__";
-         break;
-       }
-      [[fallthrough]];
-    case language_go:
-    case language_d:
-      sep = ".";
-      break;
-
-    default:
-      if (sep == nullptr)
-       return local_name;
-      break;
-    }
-
-  /* The FOR_ADA_LINKAGE_NAME flag should only affect Ada entries, so
-     disable it here if we don't need it.  */
-  if (lang != language_ada)
-    name_flags &= ~FOR_ADA_LINKAGE_NAME;
-
-  get_parent ()->write_scope (storage, sep, name_flags);
-  obstack_grow0 (storage, local_name, strlen (local_name));
-  return (const char *) obstack_finish (storage);
-}
-
-/* See cooked-index.h.  */
-
-void
-cooked_index_entry::write_scope (struct obstack *storage,
-                                const char *sep,
-                                cooked_index_full_name_flag flags) const
-{
-  if (get_parent () != nullptr)
-    get_parent ()->write_scope (storage, sep, flags);
-  /* When computing the Ada linkage name, the entry might not have
-     been canonicalized yet, so use the 'name'.  */
-  const char *local_name = ((flags & (FOR_MAIN | FOR_ADA_LINKAGE_NAME)) != 0
-                           ? name
-                           : canonical);
-  obstack_grow (storage, local_name, strlen (local_name));
-  obstack_grow (storage, sep, strlen (sep));
-}
-
-/* See cooked-index.h.  */
-
 cooked_index_entry *
 cooked_index_shard::create (sect_offset die_offset,
                            enum dwarf_tag tag,
@@ -997,10 +784,6 @@ void _initialize_cooked_index ();
 void
 _initialize_cooked_index ()
 {
-#if GDB_SELF_TEST
-  selftests::register_test ("cooked_index_entry::compare", test_compare);
-#endif
-
   add_cmd ("wait-for-index-cache", class_maintenance,
           maintenance_wait_for_index_cache, _("\
 Wait until all pending writes to the index cache have completed.\n\
index 101cf5bd57820a49074b806d4b530d76a77dd4f7..d50d1c9aa72fdf4716edc334f69092eba54ee9a0 100644 (file)
@@ -21,6 +21,7 @@
 #define GDB_DWARF2_COOKED_INDEX_H
 
 #include "dwarf2.h"
+#include "dwarf2/cooked-index-entry.h"
 #include "dwarf2/types.h"
 #include "symtab.h"
 #include "hashtab.h"
@@ -45,235 +46,6 @@ struct dwarf2_per_bfd;
 struct index_cache_store_context;
 struct cooked_index_entry;
 
-/* Flags that describe an entry in the index.  */
-enum cooked_index_flag_enum : unsigned char
-{
-  /* True if this entry is the program's "main".  */
-  IS_MAIN = 1,
-  /* True if this entry represents a "static" object.  */
-  IS_STATIC = 2,
-  /* True if this entry uses the linkage name.  */
-  IS_LINKAGE = 4,
-  /* True if this entry is just for the declaration of a type, not the
-     definition.  */
-  IS_TYPE_DECLARATION = 8,
-  /* True is parent_entry.deferred has a value rather than parent_entry
-     .resolved.  */
-  IS_PARENT_DEFERRED = 16,
-  /* True if this entry was synthesized by gdb (as opposed to coming
-     directly from the DWARF).  */
-  IS_SYNTHESIZED = 32,
-};
-DEF_ENUM_FLAGS_TYPE (enum cooked_index_flag_enum, cooked_index_flag);
-
-/* Flags used when requesting the full name of an entry.  */
-enum cooked_index_full_name_enum : unsigned char
-{
-  /* Set when requesting the name of "main".  See the method for the
-     full description.  */
-  FOR_MAIN = 1,
-  /* Set when requesting the linkage name for an Ada entry.  */
-  FOR_ADA_LINKAGE_NAME = 2,
-};
-DEF_ENUM_FLAGS_TYPE (enum cooked_index_full_name_enum, cooked_index_full_name_flag);
-
-/* Type representing either a resolved or deferred cooked_index_entry.  */
-
-union cooked_index_entry_ref
-{
-  cooked_index_entry_ref (parent_map::addr_type deferred_)
-  {
-    deferred = deferred_;
-  }
-
-  cooked_index_entry_ref (const cooked_index_entry *resolved_)
-  {
-    resolved = resolved_;
-  }
-
-  const cooked_index_entry *resolved;
-  parent_map::addr_type deferred;
-};
-
-/* Return a string representation of FLAGS.  */
-
-std::string to_string (cooked_index_flag flags);
-
-/* A cooked_index_entry represents a single item in the index.  Note
-   that two entries can be created for the same DIE -- one using the
-   name, and another one using the linkage name, if any.
-
-   This is an "open" class and the members are all directly
-   accessible.  It is read-only after the index has been fully read
-   and processed.  */
-struct cooked_index_entry : public allocate_on_obstack<cooked_index_entry>
-{
-  cooked_index_entry (sect_offset die_offset_, enum dwarf_tag tag_,
-                     cooked_index_flag flags_,
-                     enum language lang_, const char *name_,
-                     cooked_index_entry_ref parent_entry_,
-                     dwarf2_per_cu *per_cu_)
-    : name (name_),
-      tag (tag_),
-      flags (flags_),
-      lang (lang_),
-      die_offset (die_offset_),
-      per_cu (per_cu_),
-      m_parent_entry (parent_entry_)
-  {
-  }
-
-  /* Return true if this entry matches SEARCH_FLAGS.  */
-  bool matches (block_search_flags search_flags) const
-  {
-    /* Just reject type declarations.  */
-    if ((flags & IS_TYPE_DECLARATION) != 0)
-      return false;
-
-    if ((search_flags & SEARCH_STATIC_BLOCK) != 0
-       && (flags & IS_STATIC) != 0)
-      return true;
-    if ((search_flags & SEARCH_GLOBAL_BLOCK) != 0
-       && (flags & IS_STATIC) == 0)
-      return true;
-    return false;
-  }
-
-  /* Return true if this entry matches KIND.  */
-  bool matches (domain_search_flags kind) const;
-
-  /* Construct the fully-qualified name of this entry and return a
-     pointer to it.  If allocation is needed, it will be done on
-     STORAGE.
-
-     FLAGS affects the result.  If the FOR_MAIN flag is set, we are
-     computing the name of the "main" entry -- one marked
-     DW_AT_main_subprogram.  This matters for avoiding name
-     canonicalization and also a related race (if "main" computation
-     is done during finalization).
-
-     If the FOR_ADA_LINKAGE_NAME flag is set, then Ada-language
-     symbols will have their "linkage-style" name computed.  The
-     default is source-style.
-
-     If the language doesn't prescribe a separator, one can be
-     specified using DEFAULT_SEP.  */
-  const char *full_name (struct obstack *storage,
-                        cooked_index_full_name_flag name_flags = 0,
-                        const char *default_sep = nullptr) const;
-
-  /* Comparison modes for the 'compare' function.  See the function
-     for a description.  */
-  enum comparison_mode
-  {
-    MATCH,
-    SORT,
-    COMPLETE,
-  };
-
-  /* Compare two strings, case-insensitively.  Return -1 if STRA is
-     less than STRB, 0 if they are equal, and 1 if STRA is greater.
-
-     When comparing, '<' is considered to be less than all other
-     printable characters.  This ensures that "t<x>" sorts before
-     "t1", which is necessary when looking up "t".  This '<' handling
-     is to ensure that certain C++ lookups work correctly.  It is
-     inexact, and applied regardless of the search language, but this
-     is ok because callers of this code do more precise filtering
-     according to their needs.  This is also why using a
-     case-insensitive comparison works even for languages that are
-     case sensitive.
-
-     MODE controls how the comparison proceeds.
-
-     MODE==SORT is used when sorting and the only special '<' handling
-     that it does is to ensure that '<' sorts before all other
-     printable characters.  This ensures that the resulting ordering
-     will be binary-searchable.
-
-     MODE==MATCH is used when searching for a symbol.  In this case,
-     STRB must always be the search name, and STRA must be the name in
-     the index that is under consideration.  In compare mode, early
-     termination of STRB may match STRA -- for example, "t<int>" and
-     "t" will be considered to be equal.  (However, if A=="t" and
-     B=="t<int>", then this will not consider them as equal.)
-
-     MODE==COMPLETE is used when searching for a symbol for
-     completion.  In this case, STRB must always be the search name,
-     and STRA must be the name in the index that is under
-     consideration.  In completion mode, early termination of STRB
-     always results in a match.  */
-  static int compare (const char *stra, const char *strb,
-                     comparison_mode mode);
-
-  /* Compare two entries by canonical name.  */
-  bool operator< (const cooked_index_entry &other) const
-  {
-    return compare (canonical, other.canonical, SORT) < 0;
-  }
-
-  /* Set parent entry to PARENT.  */
-  void set_parent (const cooked_index_entry *parent)
-  {
-    gdb_assert ((flags & IS_PARENT_DEFERRED) == 0);
-    m_parent_entry.resolved = parent;
-  }
-
-  /* Resolve deferred parent entry to PARENT.  */
-  void resolve_parent (const cooked_index_entry *parent)
-  {
-    gdb_assert ((flags & IS_PARENT_DEFERRED) != 0);
-    flags = flags & ~IS_PARENT_DEFERRED;
-    m_parent_entry.resolved = parent;
-  }
-
-  /* Return parent entry.  */
-  const cooked_index_entry *get_parent () const
-  {
-    gdb_assert ((flags & IS_PARENT_DEFERRED) == 0);
-    return m_parent_entry.resolved;
-  }
-
-  /* Return deferred parent entry.  */
-  parent_map::addr_type get_deferred_parent () const
-  {
-    gdb_assert ((flags & IS_PARENT_DEFERRED) != 0);
-    return m_parent_entry.deferred;
-  }
-
-  /* The name as it appears in DWARF.  This always points into one of
-     the mapped DWARF sections.  Note that this may be the name or the
-     linkage name -- two entries are created for DIEs which have both
-     attributes.  */
-  const char *name;
-  /* The canonical name.  This may be equal to NAME.  */
-  const char *canonical = nullptr;
-  /* The DWARF tag.  */
-  enum dwarf_tag tag;
-  /* Any flags attached to this entry.  */
-  cooked_index_flag flags;
-  /* The language of this symbol.  */
-  ENUM_BITFIELD (language) lang : LANGUAGE_BITS;
-  /* The offset of this DIE.  */
-  sect_offset die_offset;
-  /* The CU from which this entry originates.  */
-  dwarf2_per_cu *per_cu;
-
-private:
-
-  /* A helper method for full_name.  Emits the full scope of this
-     object, followed by the separator, to STORAGE.  If this entry has
-     a parent, its write_scope method is called first.  See full_name
-     for a description of the FLAGS parameter.  */
-  void write_scope (struct obstack *storage, const char *sep,
-                   cooked_index_full_name_flag flags) const;
-
-  /* The parent entry.  This is NULL for top-level entries.
-     Otherwise, it points to the parent entry, such as a namespace or
-     class.  */
-  cooked_index_entry_ref m_parent_entry;
-};
-
 class cooked_index;
 
 /* An index of interesting DIEs.  This is "cooked", in contrast to a