aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2020-03-27 07:54:33 -0700
committerNathan Sidwell <nathan@acm.org>2020-03-27 07:54:33 -0700
commit9dba60130dc3ebf7cce8716a36672281688693f7 (patch)
tree038d92e6564dfe1bfaafff5dcb2ccf62171e78e6
parent6969ac301f2229366a812942a906257e5c060762 (diff)
downloadgcc-9dba60130dc3ebf7cce8716a36672281688693f7.zip
gcc-9dba60130dc3ebf7cce8716a36672281688693f7.tar.gz
gcc-9dba60130dc3ebf7cce8716a36672281688693f7.tar.bz2
c++: Fix ICE after ambiguous inline namespace reopen [PR94257]
Following DR2061, 'namespace F', looks for 'F's inside inline namespaces. That can result in ambiguous lookups that we failed to diagnose early enough, leading us to push a new namespace and ICE later. Diagnose the ambiguity earlier, and then pick one. PR c++/94257 * name-lookup.c (push_namespace): Triage ambiguous lookups that contain namespaces.
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/name-lookup.c60
2 files changed, 54 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5b8c5e3..7224ff1 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2020-03-27 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/94257
+ * name-lookup.c (push_namespace): Triage ambiguous lookups that
+ contain namespaces.
+
2020-03-27 Jakub Jelinek <jakub@redhat.com>
PR c++/94326
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index d00bb5f..e6dfb9c 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -7372,23 +7372,59 @@ push_namespace (tree name, bool make_inline)
name_lookup lookup (name, 0);
if (!lookup.search_qualified (current_namespace, /*usings=*/false))
;
- else if (TREE_CODE (lookup.value) != NAMESPACE_DECL)
- ;
- else if (tree dna = DECL_NAMESPACE_ALIAS (lookup.value))
+ else if (TREE_CODE (lookup.value) == TREE_LIST)
{
- /* A namespace alias is not allowed here, but if the alias
- is for a namespace also inside the current scope,
- accept it with a diagnostic. That's better than dying
- horribly. */
- if (is_nested_namespace (current_namespace, CP_DECL_CONTEXT (dna)))
+ /* An ambiguous lookup. If exactly one is a namespace, we
+ want that. If more than one is a namespace, error, but
+ pick one of them. */
+ /* DR2061 can cause us to find multiple namespaces of the same
+ name. We must treat that carefully and avoid thinking we
+ need to push a new (possibly) duplicate namespace. Hey,
+ if you want to use the same identifier within an inline
+ nest, knock yourself out. */
+ for (tree *chain = &lookup.value, next; (next = *chain);)
+ {
+ tree decl = TREE_VALUE (next);
+ if (TREE_CODE (decl) == NAMESPACE_DECL)
+ {
+ if (!ns)
+ ns = decl;
+ else if (SCOPE_DEPTH (ns) >= SCOPE_DEPTH (decl))
+ ns = decl;
+
+ /* Advance. */
+ chain = &TREE_CHAIN (next);
+ }
+ else
+ /* Stitch out. */
+ *chain = TREE_CHAIN (next);
+ }
+
+ if (TREE_CHAIN (lookup.value))
{
- error ("namespace alias %qD not allowed here, "
- "assuming %qD", lookup.value, dna);
- ns = dna;
+ error ("%<namespace %E%> is ambiguous", name);
+ print_candidates (lookup.value);
}
}
- else
+ else if (TREE_CODE (lookup.value) == NAMESPACE_DECL)
ns = lookup.value;
+
+ if (ns)
+ if (tree dna = DECL_NAMESPACE_ALIAS (ns))
+ {
+ /* A namespace alias is not allowed here, but if the alias
+ is for a namespace also inside the current scope,
+ accept it with a diagnostic. That's better than dying
+ horribly. */
+ if (is_nested_namespace (current_namespace, CP_DECL_CONTEXT (dna)))
+ {
+ error ("namespace alias %qD not allowed here, "
+ "assuming %qD", ns, dna);
+ ns = dna;
+ }
+ else
+ ns = NULL_TREE;
+ }
}
bool new_ns = false;