From 9dba60130dc3ebf7cce8716a36672281688693f7 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 27 Mar 2020 07:54:33 -0700 Subject: [PATCH] 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. --- gcc/cp/ChangeLog | 6 +++++ gcc/cp/name-lookup.c | 60 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5b8c5e329db..7224ff195d6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-03-27 Nathan Sidwell + + PR c++/94257 + * name-lookup.c (push_namespace): Triage ambiguous lookups that + contain namespaces. + 2020-03-27 Jakub Jelinek PR c++/94326 diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index d00bb5fbfa6..e6dfb9cc723 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 ("% 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; -- 2.30.2