return found;
}
+/* If DECL is suitably visible to the user, consider its name for
+ spelling correction. */
+
static void
consider_decl (tree decl, best_match <tree, const char *> &bm,
bool consider_impl_names)
bm.consider (suggestion_str);
}
+/* If DECL is suitably visible to the user, add its name to VEC and
+ return true. Otherwise return false. */
+
+static bool
+maybe_add_fuzzy_decl (auto_vec<tree> &vec, tree decl)
+{
+ /* Skip compiler-generated variables (e.g. __for_begin/__for_end
+ within range for). */
+ if (TREE_CODE (decl) == VAR_DECL && DECL_ARTIFICIAL (decl))
+ return false;
+
+ tree suggestion = DECL_NAME (decl);
+ if (!suggestion)
+ return false;
+
+ /* Don't suggest names that are for anonymous aggregate types, as
+ they are an implementation detail generated by the compiler. */
+ if (IDENTIFIER_ANON_P (suggestion))
+ return false;
+
+ vec.safe_push (suggestion);
+
+ return true;
+}
+
+/* Examing the namespace binding BINDING, and add at most one instance
+ of the name, if it contains a visible entity of interest. */
+
+void
+maybe_add_fuzzy_binding (auto_vec<tree> &vec, tree binding,
+ lookup_name_fuzzy_kind kind)
+{
+ tree value = NULL_TREE;
+
+ if (STAT_HACK_P (binding))
+ {
+ if (!STAT_TYPE_HIDDEN_P (binding)
+ && STAT_TYPE (binding))
+ {
+ if (maybe_add_fuzzy_decl (vec, STAT_TYPE (binding)))
+ return;
+ }
+ else if (!STAT_DECL_HIDDEN_P (binding))
+ value = STAT_DECL (binding);
+ }
+ else
+ value = binding;
+
+ value = ovl_skip_hidden (value);
+ if (value)
+ {
+ value = OVL_FIRST (value);
+ if (kind != FUZZY_LOOKUP_TYPENAME
+ || TREE_CODE (STRIP_TEMPLATE (value)) == TYPE_DECL)
+ if (maybe_add_fuzzy_decl (vec, value))
+ return;
+ }
+}
+
/* Helper function for lookup_name_fuzzy.
Traverse binding level LVL, looking for good name matches for NAME
(and BM). */
}
else
{
- /* Iterate over the namespace hash table, that'll have fewer
- entries than the decl list. */
+ /* We need to iterate over the namespace hash table, in order to
+ not mention hidden entities. But hash table iteration is
+ (essentially) unpredictable, our correction-distance measure
+ is very granular, and we pick the first of equal distances.
+ Hence, we need to call the distance-measurer in a predictable
+ order. So, iterate over the namespace hash, inserting
+ visible names into a vector. Then sort the vector. Then
+ determine spelling distance. */
+
tree ns = lvl->this_entity;
+ auto_vec<tree> vec;
hash_table<named_decl_hash>::iterator end
(DECL_NAMESPACE_BINDINGS (ns)->end ());
for (hash_table<named_decl_hash>::iterator iter
(DECL_NAMESPACE_BINDINGS (ns)->begin ()); iter != end; ++iter)
+ maybe_add_fuzzy_binding (vec, *iter, kind);
+
+ vec.qsort ([] (const void *a_, const void *b_)
+ {
+ return strcmp (IDENTIFIER_POINTER (*(const tree *)a_),
+ IDENTIFIER_POINTER (*(const tree *)b_));
+ });
+
+ /* Examine longest to shortest. */
+ for (unsigned ix = vec.length (); ix--;)
{
- tree binding = *iter;
- tree value = NULL_TREE;
+ const char *str = IDENTIFIER_POINTER (vec[ix]);
- if (STAT_HACK_P (binding))
- {
- if (!STAT_TYPE_HIDDEN_P (binding)
- && STAT_TYPE (binding))
- consider_decl (STAT_TYPE (binding), bm,
- consider_implementation_names);
- else if (!STAT_DECL_HIDDEN_P (binding))
- value = STAT_DECL (binding);
- }
- else
- value = binding;
+ /* Ignore internal names with spaces in them. */
+ if (strchr (str, ' '))
+ continue;
- value = ovl_skip_hidden (value);
- if (value)
- {
- value = OVL_FIRST (value);
- if (!(kind == FUZZY_LOOKUP_TYPENAME
- && TREE_CODE (STRIP_TEMPLATE (value)) != TYPE_DECL))
- consider_decl (value, bm, consider_implementation_names);
- }
+ /* Don't suggest names that are reserved for use by the
+ implementation, unless NAME began with an underscore. */
+ if (!consider_implementation_names
+ && name_reserved_for_implementation_p (str))
+ continue;
+
+ bm.consider (str);
}
}
}