On 04/19/2016 09:39 AM, Jason Merrill wrote:
cp_binding_level_find_binding_for_name can find a binding for a hidden
friend declaration, in which case we shouldn't stop looking into
anonymous namespaces. This bug blocked the use of N4381 customization
points.
This caused 71173: when looking up the name before ::, we need to
consider namespaces as well. Previously there was no way to communicate
to lookup_qualified_name that we want a type or namespace; I've fixed
that by changing the is_type_p parameter to be prefer_type with the same
meaning as the parameter to lookup_name_real.
I've also added a pseudo-tag "scope_type" for communicating this
situation from cp_parser_class_name to cp_parser_lookup_name.
scoped10.C is a test that we can still look past a namespace to find a
class with the same name when appropriate; this has never worked in GCC
before.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 5f75a91908143bde6092a10f42ee63265f340270
Author: Jason Merrill
Date: Wed May 25 11:51:53 2016 -0400
PR c++/71173 - wrong qualified lookup
PR c++/70522
* cp-tree.h (enum tag_types): Add scope_type.
* parser.c (cp_parser_class_name): Use scope_type.
(prefer_type_arg): Handle scope_type.
(cp_parser_lookup_name): Use prefer_type_arg.
* name-lookup.c (lookup_qualified_name): Change bool is_type_p to
int prefer_type, use lookup_flags.
* name-lookup.h: Adjust.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ad21cdf..c2be21c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4601,7 +4601,8 @@ enum tag_types {
class_type,/* "class" types. */
union_type,/* "union" types. */
enum_type, /* "enum" types. */
- typename_type /* "typename" types. */
+ typename_type, /* "typename" types. */
+ scope_type /* namespace or tagged type of a name followed by :: */
};
/* The various kinds of lvalues we distinguish. */
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index d32a153..eb128db 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -4507,8 +4507,10 @@ unqualified_namespace_lookup (tree name, int flags)
}
/* Look up NAME (an IDENTIFIER_NODE) in SCOPE (either a NAMESPACE_DECL
- or a class TYPE). If IS_TYPE_P is TRUE, then ignore non-type
- bindings.
+ or a class TYPE).
+
+ If PREFER_TYPE is > 0, we only return TYPE_DECLs or namespaces.
+ If PREFER_TYPE is > 1, we only return TYPE_DECLs.
Returns a DECL (or OVERLOAD, or BASELINK) representing the
declaration found. If no suitable declaration can be found,
@@ -4516,28 +4518,25 @@ unqualified_namespace_lookup (tree name, int flags)
neither a class-type nor a namespace a diagnostic is issued. */
tree
-lookup_qualified_name (tree scope, tree name, bool is_type_p, bool complain,
+lookup_qualified_name (tree scope, tree name, int prefer_type, bool complain,
bool find_hidden)
{
- int flags = 0;
tree t = NULL_TREE;
- if (find_hidden)
-flags |= LOOKUP_HIDDEN;
-
if (TREE_CODE (scope) == NAMESPACE_DECL)
{
struct scope_binding binding = EMPTY_SCOPE_BINDING;
- if (is_type_p)
- flags |= LOOKUP_PREFER_TYPES;
+ int flags = lookup_flags (prefer_type, /*namespaces_only*/false);
+ if (find_hidden)
+ flags |= LOOKUP_HIDDEN;
if (qualified_lookup_using_namespace (name, scope, , flags))
t = binding.value;
}
else if (cxx_dialect != cxx98 && TREE_CODE (scope) == ENUMERAL_TYPE)
t = lookup_enumerator (scope, name);
else if (is_class_type (scope, complain))
-t = lookup_member (scope, name, 2, is_type_p, tf_warning_or_error);
+t = lookup_member (scope, name, 2, prefer_type, tf_warning_or_error);
if (!t)
return error_mark_node;
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index 7e39b6c..2f8447a 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -327,7 +327,7 @@ extern tree namespace_binding (tree, tree);
extern void set_namespace_binding (tree, tree, tree);
extern bool hidden_name_p (tree);
extern tree remove_hidden_names (tree);
-extern tree lookup_qualified_name (tree, tree, bool, bool, /*hidden*/bool = false);
+extern tree lookup_qualified_name (tree, tree, int, bool, /*hidden*/bool = false);
extern tree lookup_name_nonclass (tree);
extern tree lookup_name_innermost_nonclass_level (tree);
extern bool is_local_extern (tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d21230f..546aada 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -21190,7 +21190,7 @@ cp_parser_class_name (cp_parser *parser,
resolution operator, object, function, and enumerator
names are ignored. */
if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
- tag_type = typename_type;
+ tag_type = scope_type;
/* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier,
tag_type,
@@ -24595,6 +24595,24 @@ cp_parser_nested_requirement (cp_parser *parser)