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 \
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 \
--- /dev/null
+/* 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
+}
--- /dev/null
+/* 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 */
#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
/* 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,
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\
#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"
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