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> 2017-06-02 Bernd Edlinger <bernd.edlinger@hotmail.de>
* typeck.c (cp_build_binary_op): Implement the -Wsizeof_pointer_div * 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 static void
collect_source_refs (tree namespc) collect_source_refs (tree namespc)
{ {
tree t;
if (!namespc)
return;
/* Iterate over names in this name space. */ /* Iterate over names in this name space. */
for (t = NAMESPACE_LEVEL (namespc)->names; t; t = TREE_CHAIN (t)) for (tree t = NAMESPACE_LEVEL (namespc)->names; t; t = TREE_CHAIN (t))
if (!DECL_IS_BUILTIN (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)); 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, /* Collect decls relevant to SOURCE_FILE from all namespaces recursively,
@ -4075,17 +4068,16 @@ collect_source_refs (tree namespc)
static void static void
collect_ada_namespace (tree namespc, const char *source_file) collect_ada_namespace (tree namespc, const char *source_file)
{ {
if (!namespc) tree decl = NAMESPACE_LEVEL (namespc)->names;
return;
/* Collect decls from this namespace */ /* Collect decls from this namespace. This will skip
collect_ada_nodes (NAMESPACE_LEVEL (namespc)->names, source_file); NAMESPACE_DECLs (both aliases and regular, it cannot tell). */
collect_ada_nodes (decl, source_file);
/* Collect siblings, if any */ /* Now scan for namespace children, and dump them. */
collect_ada_namespace (TREE_CHAIN (namespc), source_file); for (; decl; decl = TREE_CHAIN (decl))
if (TREE_CODE (decl) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (decl))
/* Collect children, if any */ collect_ada_namespace (decl, source_file);
collect_ada_namespace (NAMESPACE_LEVEL (namespc)->namespaces, source_file);
} }
/* Returns true iff there is a definition available for variable or /* 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); gcc_assert (b->kind != sk_class);
if (TREE_CODE (decl) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (decl)) /* Make sure we don't create a circular list. xref_tag can end
{ up pushing the same artificial decl more than once. We
/* Inner namespaces get their own chain, to make walking should have already detected that in update_binding. */
simpler. */ gcc_assert (b->names != decl);
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);
/* We build up the list in reverse order, and reverse it later if /* We build up the list in reverse order, and reverse it later if
necessary. */ necessary. */
TREE_CHAIN (decl) = b->names; TREE_CHAIN (decl) = b->names;
b->names = decl; b->names = decl;
/* If appropriate, add decl to separate list of statics. We /* If appropriate, add decl to separate list of statics. We
include extern variables because they might turn out to be include extern variables because they might turn out to be
static later. It's OK for this list to contain a few false static later. It's OK for this list to contain a few false
positives. */ positives. */
if (b->kind == sk_namespace) if (b->kind == sk_namespace
if ((VAR_P (decl) && ((VAR_P (decl)
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
|| (TREE_CODE (decl) == FUNCTION_DECL || (TREE_CODE (decl) == FUNCTION_DECL
&& (!TREE_PUBLIC (decl) && (!TREE_PUBLIC (decl)
|| decl_anon_ns_mem_p (decl) || decl_anon_ns_mem_p (decl)
|| DECL_DECLARED_INLINE_P (decl)))) || DECL_DECLARED_INLINE_P (decl)))))
vec_safe_push (static_decls, decl); vec_safe_push (static_decls, decl);
}
} }
/* Find the binding for NAME in the local binding level B. */ /* 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) bool suggest_misspellings)
{ {
vec<tree> candidates = vNULL; vec<tree> candidates = vNULL;
vec<tree> namespaces_to_search = vNULL; vec<tree> worklist = vNULL;
int max_to_search = PARAM_VALUE (CXX_MAX_NAMESPACES_FOR_DIAGNOSTIC_HELP); unsigned limit = PARAM_VALUE (CXX_MAX_NAMESPACES_FOR_DIAGNOSTIC_HELP);
int n_searched = 0; bool limited = false;
tree t;
unsigned ix;
namespaces_to_search.safe_push (global_namespace); /* Breadth-first search of namespaces. Up to limit namespaces
searched (limit zero == unlimited). */
while (!namespaces_to_search.is_empty () worklist.safe_push (global_namespace);
&& n_searched < max_to_search) for (unsigned ix = 0; ix != worklist.length (); ix++)
{ {
tree scope = namespaces_to_search.pop (); tree ns = worklist[ix];
name_lookup lookup (name, 0);
cp_binding_level *level = NAMESPACE_LEVEL (scope);
n_searched++; if (tree value = ovl_skip_hidden (find_namespace_value (ns, name)))
candidates.safe_push (value);
/* Look in this namespace. */ if (!limited)
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)
{ {
const char *fuzzy_name = lookup_name_fuzzy (name, FUZZY_LOOKUP_NAME); /* Look for child namespaces. We have to do this
if (fuzzy_name) 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); if (worklist.length () == limit)
richloc.add_fixit_replace (fuzzy_name); {
inform_at_rich_loc (&richloc, "suggested alternative: %qs", /* Unconditionally warn that the search was truncated. */
fuzzy_name); 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 (), if (candidates.length ())
"suggested alternative:", {
"suggested alternatives:"); 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 (val), " %qE", val);
inform (location_of (t), " %qE", t); }
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 /* 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. */ are wrapped in TREE_LISTs; the TREE_VALUE is the OVERLOAD. */
tree names; tree names;
/* A chain of NAMESPACE_DECL nodes. */
tree namespaces;
/* A list of USING_DECL nodes. */ /* A list of USING_DECL nodes. */
tree usings; 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> 2017-06-02 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/80903 PR rtl-optimization/80903

View File

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