From: Tom Tromey Date: Mon, 24 Mar 2025 21:11:02 +0000 (-0600) Subject: Move cooked_index_entry to new files X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5bc2273db46b9a55c768473cc9b835f076a27c64;p=thirdparty%2Fbinutils-gdb.git Move cooked_index_entry to new files 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 --- diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 5329af31e73..b4e54071eed 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -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 index 00000000000..197f62aee51 --- /dev/null +++ b/gdb/dwarf2/cooked-index-entry.c @@ -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 . */ + +#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" match "func>". 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", "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>", + "name>", + mode_compare) == 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_compare) == 0); + SELF_CHECK (cooked_index_entry::compare ("name>", "name>", "name 0); + SELF_CHECK (cooked_index_entry::compare ("abcd", "", mode_complete) == 0); + + SELF_CHECK (cooked_index_entry::compare ("func", "func", + mode_sort) == 0); + SELF_CHECK (cooked_index_entry::compare ("func", "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 index 00000000000..bb47e32ffe9 --- /dev/null +++ b/gdb/dwarf2/cooked-index-entry.h @@ -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 . */ + +#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 (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" 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" and + "t" will be considered to be equal. (However, if A=="t" and + B=="t", 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 */ diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c index 32e299ffd10..9d5f152045b 100644 --- a/gdb/dwarf2/cooked-index.c +++ b/gdb/dwarf2/cooked-index.c @@ -32,8 +32,6 @@ #include "observable.h" #include "run-on-main-thread.h" #include -#include "gdbsupport/gdb-safe-ctype.h" -#include "gdbsupport/selftest.h" #include "gdbsupport/task-group.h" #include "gdbsupport/thread-pool.h" #include @@ -44,22 +42,6 @@ here, and then these are all waited for before exit proceeds. */ static gdb::unordered_set 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" match "func>". 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", "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>", - "name>", - mode_compare) == 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_compare) == 0); - SELF_CHECK (cooked_index_entry::compare ("name>", "name>", "name 0); - SELF_CHECK (cooked_index_entry::compare ("abcd", "", mode_complete) == 0); - - SELF_CHECK (cooked_index_entry::compare ("func", "func", - mode_sort) == 0); - SELF_CHECK (cooked_index_entry::compare ("func", "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\ diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h index 101cf5bd578..d50d1c9aa72 100644 --- a/gdb/dwarf2/cooked-index.h +++ b/gdb/dwarf2/cooked-index.h @@ -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 (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" 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" and - "t" will be considered to be equal. (However, if A=="t" and - B=="t", 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