name-lookup.h (cp_binding_level): Lose namespaces field.

* name-lookup.h (cp_binding_level): Lose namespaces field.
	* name-lookup.c (add_decl_to_level): Chain namespaces on the names
	list.
	(suggest_alternatives_for): Adjust for namespace list.  Do
	breadth-first search.
	* decl2.c (collect_source_refs): Namespaces are on the regulr
	list.
	(collect_ada_namespace): Likewise.

	* g++.dg/pr45330.C: Adjust.  Check breadth-firstness.

From-SVN: r248821
This commit is contained in:
Nathan Sidwell 2017-06-02 11:02:26 +00:00 committed by Nathan Sidwell
parent 643a9684fa
commit c957e9c052
6 changed files with 116 additions and 112 deletions

View File

@ -1,3 +1,14 @@
2017-06-02 Nathan Sidwell <nathan@acm.org>
* name-lookup.h (cp_binding_level): Lose namespaces field.
* name-lookup.c (add_decl_to_level): Chain namespaces on the names
list.
(suggest_alternatives_for): Adjust for namespace list. Do
breadth-first search.
* decl2.c (collect_source_refs): Namespaces are on the regulr
list.
(collect_ada_namespace): Likewise.
2017-06-02 Bernd Edlinger <bernd.edlinger@hotmail.de>
* typeck.c (cp_build_binary_op): Implement the -Wsizeof_pointer_div

View File

@ -4052,21 +4052,14 @@ cpp_check (tree t, cpp_operation op)
static void
collect_source_refs (tree namespc)
{
tree t;
if (!namespc)
return;
/* Iterate over names in this name space. */
for (t = NAMESPACE_LEVEL (namespc)->names; t; t = TREE_CHAIN (t))
if (!DECL_IS_BUILTIN (t) )
for (tree t = NAMESPACE_LEVEL (namespc)->names; t; t = TREE_CHAIN (t))
if (DECL_IS_BUILTIN (t))
;
else if (TREE_CODE (t) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (t))
collect_source_refs (t);
else
collect_source_ref (DECL_SOURCE_FILE (t));
/* Dump siblings, if any */
collect_source_refs (TREE_CHAIN (namespc));
/* Dump children, if any */
collect_source_refs (NAMESPACE_LEVEL (namespc)->namespaces);
}
/* Collect decls relevant to SOURCE_FILE from all namespaces recursively,
@ -4075,17 +4068,16 @@ collect_source_refs (tree namespc)
static void
collect_ada_namespace (tree namespc, const char *source_file)
{
if (!namespc)
return;
tree decl = NAMESPACE_LEVEL (namespc)->names;
/* Collect decls from this namespace */
collect_ada_nodes (NAMESPACE_LEVEL (namespc)->names, source_file);
/* Collect decls from this namespace. This will skip
NAMESPACE_DECLs (both aliases and regular, it cannot tell). */
collect_ada_nodes (decl, source_file);
/* Collect siblings, if any */
collect_ada_namespace (TREE_CHAIN (namespc), source_file);
/* Collect children, if any */
collect_ada_namespace (NAMESPACE_LEVEL (namespc)->namespaces, source_file);
/* Now scan for namespace children, and dump them. */
for (; decl; decl = TREE_CHAIN (decl))
if (TREE_CODE (decl) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (decl))
collect_ada_namespace (decl, source_file);
}
/* Returns true iff there is a definition available for variable or

View File

@ -115,38 +115,28 @@ add_decl_to_level (cp_binding_level *b, tree decl)
{
gcc_assert (b->kind != sk_class);
if (TREE_CODE (decl) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (decl))
{
/* Inner namespaces get their own chain, to make walking
simpler. */
DECL_CHAIN (decl) = b->namespaces;
b->namespaces = decl;
}
else
{
/* Make sure we don't create a circular list. xref_tag can end
up pushing the same artificial decl more than once. We
should have already detected that in update_binding. */
gcc_assert (b->names != decl);
/* Make sure we don't create a circular list. xref_tag can end
up pushing the same artificial decl more than once. We
should have already detected that in update_binding. */
gcc_assert (b->names != decl);
/* We build up the list in reverse order, and reverse it later if
necessary. */
TREE_CHAIN (decl) = b->names;
b->names = decl;
/* We build up the list in reverse order, and reverse it later if
necessary. */
TREE_CHAIN (decl) = b->names;
b->names = decl;
/* If appropriate, add decl to separate list of statics. We
include extern variables because they might turn out to be
static later. It's OK for this list to contain a few false
positives. */
if (b->kind == sk_namespace)
if ((VAR_P (decl)
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
|| (TREE_CODE (decl) == FUNCTION_DECL
&& (!TREE_PUBLIC (decl)
|| decl_anon_ns_mem_p (decl)
|| DECL_DECLARED_INLINE_P (decl))))
vec_safe_push (static_decls, decl);
}
/* If appropriate, add decl to separate list of statics. We
include extern variables because they might turn out to be
static later. It's OK for this list to contain a few false
positives. */
if (b->kind == sk_namespace
&& ((VAR_P (decl)
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
|| (TREE_CODE (decl) == FUNCTION_DECL
&& (!TREE_PUBLIC (decl)
|| decl_anon_ns_mem_p (decl)
|| DECL_DECLARED_INLINE_P (decl)))))
vec_safe_push (static_decls, decl);
}
/* Find the binding for NAME in the local binding level B. */
@ -4708,70 +4698,74 @@ suggest_alternatives_for (location_t location, tree name,
bool suggest_misspellings)
{
vec<tree> candidates = vNULL;
vec<tree> namespaces_to_search = vNULL;
int max_to_search = PARAM_VALUE (CXX_MAX_NAMESPACES_FOR_DIAGNOSTIC_HELP);
int n_searched = 0;
tree t;
unsigned ix;
vec<tree> worklist = vNULL;
unsigned limit = PARAM_VALUE (CXX_MAX_NAMESPACES_FOR_DIAGNOSTIC_HELP);
bool limited = false;
namespaces_to_search.safe_push (global_namespace);
while (!namespaces_to_search.is_empty ()
&& n_searched < max_to_search)
/* Breadth-first search of namespaces. Up to limit namespaces
searched (limit zero == unlimited). */
worklist.safe_push (global_namespace);
for (unsigned ix = 0; ix != worklist.length (); ix++)
{
tree scope = namespaces_to_search.pop ();
name_lookup lookup (name, 0);
cp_binding_level *level = NAMESPACE_LEVEL (scope);
tree ns = worklist[ix];
n_searched++;
if (tree value = ovl_skip_hidden (find_namespace_value (ns, name)))
candidates.safe_push (value);
/* Look in this namespace. */
if (qualified_namespace_lookup (scope, &lookup))
candidates.safe_push (lookup.value);
/* Add child namespaces. */
for (t = level->namespaces; t; t = DECL_CHAIN (t))
namespaces_to_search.safe_push (t);
}
/* If we stopped before we could examine all namespaces, inform the
user. Do this even if we don't have any candidates, since there
might be more candidates further down that we weren't able to
find. */
if (n_searched >= max_to_search
&& !namespaces_to_search.is_empty ())
inform (location,
"maximum limit of %d namespaces searched for %qE",
max_to_search, name);
namespaces_to_search.release ();
/* Nothing useful to report for NAME. Report on likely misspellings,
or do nothing. */
if (candidates.is_empty ())
{
if (suggest_misspellings)
if (!limited)
{
const char *fuzzy_name = lookup_name_fuzzy (name, FUZZY_LOOKUP_NAME);
if (fuzzy_name)
/* Look for child namespaces. We have to do this
indirectly because they are chained in reverse order,
which is confusing to the user. */
vec<tree> children = vNULL;
for (tree decl = NAMESPACE_LEVEL (ns)->names;
decl; decl = TREE_CHAIN (decl))
if (TREE_CODE (decl) == NAMESPACE_DECL
&& !DECL_NAMESPACE_ALIAS (decl))
children.safe_push (decl);
while (!limited && !children.is_empty ())
{
gcc_rich_location richloc (location);
richloc.add_fixit_replace (fuzzy_name);
inform_at_rich_loc (&richloc, "suggested alternative: %qs",
fuzzy_name);
if (worklist.length () == limit)
{
/* Unconditionally warn that the search was truncated. */
inform (location,
"maximum limit of %d namespaces searched for %qE",
limit, name);
limited = true;
}
else
worklist.safe_push (children.pop ());
}
children.release ();
}
return;
}
worklist.release ();
inform_n (location, candidates.length (),
"suggested alternative:",
"suggested alternatives:");
if (candidates.length ())
{
inform_n (location, candidates.length (),
"suggested alternative:",
"suggested alternatives:");
for (unsigned ix = 0; ix != candidates.length (); ix++)
{
tree val = candidates[ix];
FOR_EACH_VEC_ELT (candidates, ix, t)
inform (location_of (t), " %qE", t);
inform (location_of (val), " %qE", val);
}
candidates.release ();
}
else if (!suggest_misspellings)
;
else if (const char *fuzzy = lookup_name_fuzzy (name, FUZZY_LOOKUP_NAME))
{
/* Show a spelling correction. */
gcc_rich_location richloc (location);
candidates.release ();
richloc.add_fixit_replace (fuzzy);
inform_at_rich_loc (&richloc, "suggested alternative: %qs", fuzzy);
}
}
/* Subroutine of maybe_suggest_missing_header for handling unrecognized names

View File

@ -188,9 +188,6 @@ struct GTY(()) cp_binding_level {
are wrapped in TREE_LISTs; the TREE_VALUE is the OVERLOAD. */
tree names;
/* A chain of NAMESPACE_DECL nodes. */
tree namespaces;
/* A list of USING_DECL nodes. */
tree usings;

View File

@ -1,3 +1,7 @@
2017-06-02 Nathan Sidwell <nathan@acm.org>
* g++.dg/pr45330.C: Adjust. Check breadth-firstness.
2017-06-02 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/80903

View File

@ -1,17 +1,23 @@
// { dg-do compile }
// Search std, __cxxabiv1, and global namespaces, plus one more.
// { dg-options "--param cxx-max-namespaces-for-diagnostic-help=4" }
// Search std, __cxxabiv1, and global namespaces, plus two more,
// breadth first
#define NSPACE(NAME) namespace NAME { int foo; }
// { dg-options "--param cxx-max-namespaces-for-diagnostic-help=5" }
// ::, std and __cxxabiv1
namespace A
{
int foo; // { dg-message "A::foo" "suggested alternative" }
namespace A0
{
int foo; // not me
}
}
namespace B
{
int foo;
int foo; // { dg-message "B::foo" "suggested alternative" }
}
namespace C
@ -32,6 +38,6 @@ namespace E
int bar()
{
return foo; // { dg-error "was not declared" }
// { dg-message "maximum limit of 4 namespaces" "maximum limit" { target *-*-* } .-1 }
// { dg-message "maximum limit of 5 namespaces" "maximum limit" { target *-*-* } .-1 }
// { dg-message "suggested alternative" "suggested alternative" { target *-*-* } .-2 }
}