return block_iter_match_step (iterator, false);
}
+/* See block.h. */
+
+bool
+best_symbol (struct symbol *a, const domain_search_flags domain)
+{
+ if (a->loc_class () == LOC_UNRESOLVED)
+ return false;
+
+ if ((domain & SEARCH_VAR_DOMAIN) != 0)
+ return a->domain () == VAR_DOMAIN;
+
+ return a->matches (domain);
+}
+
+/* See block.h. */
+
+struct symbol *
+better_symbol (struct symbol *a, struct symbol *b,
+ const domain_search_flags domain)
+{
+ if (a == NULL)
+ return b;
+ if (b == NULL)
+ return a;
+
+ if (a->matches (domain) && !b->matches (domain))
+ return a;
+
+ if (b->matches (domain) && !a->matches (domain))
+ return b;
+
+ if (a->loc_class () != LOC_UNRESOLVED && b->loc_class () == LOC_UNRESOLVED)
+ return a;
+
+ if (b->loc_class () != LOC_UNRESOLVED && a->loc_class () == LOC_UNRESOLVED)
+ return b;
+
+ return a;
+}
+
/* See block.h.
Note that if NAME is the demangled form of a C++ symbol, we will fail
{
for (symbol *sym : block_iterator_range (block, &name))
{
- if (!sym->matches (domain))
- continue;
-
/* With the fix for PR gcc/debug/91507, we get for:
...
extern char *zzz[];
doesn't work either because the type of the decl does not specify a
size.
- To fix this, we prefer definitions over declarations.
+ To fix this, we prefer def over decl in best_symbol and
+ better_symbol.
In absence of the gcc fix, both def and decl have type char *[], so
the only option to make this work is improve the fallback to use the
size of the minimal symbol. Filed as PR exp/24989. */
- if (sym->is_definition ())
+ if (best_symbol (sym, domain))
{
best_symtab = symtab;
currently_best = { sym, block };
return true;
}
- if (currently_best.symbol == nullptr)
+ /* This is a bit of a hack, but 'matches' might ignore
+ STRUCT vs VAR domain symbols. So if a matching symbol is found,
+ make sure there is no "better" matching symbol, i.e., one with
+ exactly the same domain. PR 16253. */
+ if (sym->matches (domain))
{
- best_symtab = symtab;
- currently_best = { sym, block };
+ symbol *better = better_symbol (sym, currently_best.symbol, domain);
+ if (better != currently_best.symbol)
+ {
+ best_symtab = symtab;
+ currently_best = { better, block };
+ }
}
}
return iterator_range<block_iterator_wrapper> (std::move (begin));
}
+/* Return true if symbol A is the best match possible for DOMAIN. */
+
+extern bool best_symbol (struct symbol *a, const domain_search_flags domain);
+
+/* Return symbol B if it is a better match than symbol A for DOMAIN.
+ Otherwise return A. */
+
+extern struct symbol *better_symbol (struct symbol *a, struct symbol *b,
+ const domain_search_flags domain);
+
/* Search BLOCK for symbol NAME in DOMAIN. */
extern struct symbol *block_lookup_symbol (const struct block *block,
const domain_search_flags domain);
/* When searching for a symbol, the "best" symbol is preferred over
- one that is merely acceptable. This class keeps track of this
- distinction while searching. */
+ one that is merely acceptable. See 'best_symbol'. This class
+ keeps track of this distinction while searching. */
struct best_symbol_tracker
{
std::string copy = copy_name (yylval.sval);
- /* Prefer variables over functions or types. This preserves some
- historical parser behavior. */
- bsym = lookup_symbol (copy.c_str (), block, SEARCH_VAR_DOMAIN,
+ bsym = lookup_symbol (copy.c_str (), block, SEARCH_VFT,
&is_a_field_of_this);
- if (bsym.symbol == nullptr)
- bsym = lookup_symbol (copy.c_str (), block,
- SEARCH_FUNCTION_DOMAIN | SEARCH_TYPE_DOMAIN,
- &is_a_field_of_this);
if (bsym.symbol && bsym.symbol->loc_class () == LOC_BLOCK)
{
sym = lookup_symbol_in_block (name,
symbol_name_match_type::FULL,
global_block, domain);
- if (sym != nullptr && sym->is_definition ())
+ if (sym != NULL && best_symbol (sym, domain))
return { sym, global_block };
}
block_symbol bs
= lookup_global_or_static_symbol (name, GLOBAL_BLOCK, objfile, domain);
- /* Prefer a definition over a declaration. (At this point, SYM is
- either nullptr or a declaration.) */
- if (bs.symbol != nullptr && bs.symbol->is_definition ())
- return bs;
- /* Prefer a declaration if that's all we have. */
- if (bs.symbol != nullptr && sym == nullptr)
+ if (better_symbol (sym, bs.symbol, domain) == sym)
+ return { sym, global_block };
+ else
return bs;
- /* Return either an empty result or the declaration we found in the
- "local" global block. */
- return { sym, global_block };
}
/* See symtab.h. */
return this->impl ().loc_class;
}
- /* Return true if the symbol is not LOC_UNRESOLVED -- that is, if it
- is a definition and not just a declaration. */
- bool is_definition () const
- {
- return loc_class () != LOC_UNRESOLVED;
- }
-
/* Return true if this symbol's domain matches FLAGS. */
bool matches (domain_search_flags flags) const;