+class probe;
+struct lookup_name_info;
+
+/* How to match a lookup name against a symbol search name. */
+enum class symbol_name_match_type
+{
+ /* Wild matching. Matches unqualified symbol names in all
+ namespace/module/packages, etc. */
+ WILD,
+
+ /* Full matching. The lookup name indicates a fully-qualified name,
+ and only matches symbol search names in the specified
+ namespace/module/package. */
+ FULL,
+
+ /* Expression matching. The same as FULL matching in most
+ languages. The same as WILD matching in Ada. */
+ EXPRESSION,
+};
+
+/* Hash the given symbol search name according to LANGUAGE's
+ rules. */
+extern unsigned int search_name_hash (enum language language,
+ const char *search_name);
+
+/* Ada-specific bits of a lookup_name_info object. This is lazily
+ constructed on demand. */
+
+class ada_lookup_name_info final
+{
+ public:
+ /* Construct. */
+ explicit ada_lookup_name_info (const lookup_name_info &lookup_name);
+
+ /* Compare SYMBOL_SEARCH_NAME with our lookup name, using MATCH_TYPE
+ as name match type. Returns true if there's a match, false
+ otherwise. If non-NULL, store the matching results in MATCH. */
+ bool matches (const char *symbol_search_name,
+ symbol_name_match_type match_type,
+ completion_match *match) const;
+
+ /* The Ada-encoded lookup name. */
+ const std::string &lookup_name () const
+ { return m_encoded_name; }
+
+ /* Return true if we're supposed to be doing a wild match look
+ up. */
+ bool wild_match_p () const
+ { return m_wild_match_p; }
+
+ /* Return true if we're looking up a name inside package
+ Standard. */
+ bool standard_p () const
+ { return m_standard_p; }
+
+ private:
+ /* The Ada-encoded lookup name. */
+ std::string m_encoded_name;
+
+ /* Whether the user-provided lookup name was Ada encoded. If so,
+ then return encoded names in the 'matches' method's 'completion
+ match result' output. */
+ bool m_encoded_p : 1;
+
+ /* True if really doing wild matching. Even if the user requests
+ wild matching, some cases require full matching. */
+ bool m_wild_match_p : 1;
+
+ /* True if doing a verbatim match. This is true if the decoded
+ version of the symbol name is wrapped in '<'/'>'. This is an
+ escape hatch users can use to look up symbols the Ada encoding
+ does not understand. */
+ bool m_verbatim_p : 1;
+
+ /* True if the user specified a symbol name that is inside package
+ Standard. Symbol names inside package Standard are handled
+ specially. We always do a non-wild match of the symbol name
+ without the "standard__" prefix, and only search static and
+ global symbols. This was primarily introduced in order to allow
+ the user to specifically access the standard exceptions using,
+ for instance, Standard.Constraint_Error when Constraint_Error is
+ ambiguous (due to the user defining its own Constraint_Error
+ entity inside its program). */
+ bool m_standard_p : 1;
+};
+
+/* Language-specific bits of a lookup_name_info object, for languages
+ that do name searching using demangled names (C++/D/Go). This is
+ lazily constructed on demand. */
+
+struct demangle_for_lookup_info final
+{
+public:
+ demangle_for_lookup_info (const lookup_name_info &lookup_name,
+ language lang);
+
+ /* The demangled lookup name. */
+ const std::string &lookup_name () const
+ { return m_demangled_name; }
+
+private:
+ /* The demangled lookup name. */
+ std::string m_demangled_name;
+};
+
+/* Object that aggregates all information related to a symbol lookup
+ name. I.e., the name that is matched against the symbol's search
+ name. Caches per-language information so that it doesn't require
+ recomputing it for every symbol comparison, like for example the
+ Ada encoded name and the symbol's name hash for a given language.
+ The object is conceptually immutable once constructed, and thus has
+ no setters. This is to prevent some code path from tweaking some
+ property of the lookup name for some local reason and accidentally
+ altering the results of any continuing search(es).
+ lookup_name_info objects are generally passed around as a const
+ reference to reinforce that. (They're not passed around by value
+ because they're not small.) */
+class lookup_name_info final
+{
+ public:
+ /* Create a new object. */
+ lookup_name_info (std::string name,
+ symbol_name_match_type match_type,
+ bool completion_mode = false,
+ bool ignore_parameters = false)
+ : m_match_type (match_type),
+ m_completion_mode (completion_mode),
+ m_ignore_parameters (ignore_parameters),
+ m_name (std::move (name))
+ {}
+
+ /* Getters. See description of each corresponding field. */
+ symbol_name_match_type match_type () const { return m_match_type; }
+ bool completion_mode () const { return m_completion_mode; }
+ const std::string &name () const { return m_name; }
+ const bool ignore_parameters () const { return m_ignore_parameters; }
+
+ /* Return a version of this lookup name that is usable with
+ comparisons against symbols have no parameter info, such as
+ psymbols and GDB index symbols. */
+ lookup_name_info make_ignore_params () const
+ {
+ return lookup_name_info (m_name, m_match_type, m_completion_mode,
+ true /* ignore params */);
+ }
+
+ /* Get the search name hash for searches in language LANG. */
+ unsigned int search_name_hash (language lang) const
+ {
+ /* Only compute each language's hash once. */
+ if (!m_demangled_hashes_p[lang])
+ {
+ m_demangled_hashes[lang]
+ = ::search_name_hash (lang, language_lookup_name (lang).c_str ());
+ m_demangled_hashes_p[lang] = true;
+ }
+ return m_demangled_hashes[lang];
+ }
+
+ /* Get the search name for searches in language LANG. */
+ const std::string &language_lookup_name (language lang) const
+ {
+ switch (lang)
+ {
+ case language_ada:
+ return ada ().lookup_name ();
+ case language_cplus:
+ return cplus ().lookup_name ();
+ case language_d:
+ return d ().lookup_name ();
+ case language_go:
+ return go ().lookup_name ();
+ default:
+ return m_name;
+ }
+ }
+
+ /* Get the Ada-specific lookup info. */
+ const ada_lookup_name_info &ada () const
+ {
+ maybe_init (m_ada);
+ return *m_ada;
+ }
+
+ /* Get the C++-specific lookup info. */
+ const demangle_for_lookup_info &cplus () const
+ {
+ maybe_init (m_cplus, language_cplus);
+ return *m_cplus;
+ }
+
+ /* Get the D-specific lookup info. */
+ const demangle_for_lookup_info &d () const
+ {
+ maybe_init (m_d, language_d);
+ return *m_d;
+ }
+
+ /* Get the Go-specific lookup info. */
+ const demangle_for_lookup_info &go () const
+ {
+ maybe_init (m_go, language_go);
+ return *m_go;
+ }
+
+ /* Get a reference to a lookup_name_info object that matches any
+ symbol name. */
+ static const lookup_name_info &match_any ();
+
+private:
+ /* Initialize FIELD, if not initialized yet. */
+ template<typename Field, typename... Args>
+ void maybe_init (Field &field, Args&&... args) const
+ {
+ if (!field)
+ field.emplace (*this, std::forward<Args> (args)...);
+ }
+
+ /* The lookup info as passed to the ctor. */
+ symbol_name_match_type m_match_type;
+ bool m_completion_mode;
+ bool m_ignore_parameters;
+ std::string m_name;
+
+ /* Language-specific info. These fields are filled lazily the first
+ time a lookup is done in the corresponding language. They're
+ mutable because lookup_name_info objects are typically passed
+ around by const reference (see intro), and they're conceptually
+ "cache" that can always be reconstructed from the non-mutable
+ fields. */
+ mutable gdb::optional<ada_lookup_name_info> m_ada;
+ mutable gdb::optional<demangle_for_lookup_info> m_cplus;
+ mutable gdb::optional<demangle_for_lookup_info> m_d;
+ mutable gdb::optional<demangle_for_lookup_info> m_go;
+
+ /* The demangled hashes. Stored in an array with one entry for each
+ possible language. The second array records whether we've
+ already computed the each language's hash. (These are separate
+ arrays instead of a single array of optional<unsigned> to avoid
+ alignment padding). */
+ mutable std::array<unsigned int, nr_languages> m_demangled_hashes;
+ mutable std::array<bool, nr_languages> m_demangled_hashes_p {};
+};
+
+/* Comparison function for completion symbol lookup.
+
+ Returns true if the symbol name matches against LOOKUP_NAME.
+
+ SYMBOL_SEARCH_NAME should be a symbol's "search" name.
+
+ On success and if non-NULL, MATCH is set to point to the symbol
+ name as should be presented to the user as a completion match list
+ element. In most languages, this is the same as the symbol's
+ search name, but in some, like Ada, the display name is dynamically
+ computed within the comparison routine. */
+typedef bool (symbol_name_matcher_ftype)
+ (const char *symbol_search_name,
+ const lookup_name_info &lookup_name,
+ completion_match *match);