Commit 1b22fc54 by Jason Merrill Committed by Jason Merrill

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.

From-SVN: r236736
parent 04080f22
2016-05-25 Jason Merrill <jason@redhat.com>
PR c++/71173
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.
2016-05-24 Cesar Philippidis <cesar@codesourcery.com> 2016-05-24 Cesar Philippidis <cesar@codesourcery.com>
* parser.c (cp_parser_oacc_declare): Add support for * parser.c (cp_parser_oacc_declare): Add support for
......
...@@ -4601,7 +4601,8 @@ enum tag_types { ...@@ -4601,7 +4601,8 @@ enum tag_types {
class_type, /* "class" types. */ class_type, /* "class" types. */
union_type, /* "union" types. */ union_type, /* "union" types. */
enum_type, /* "enum" 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. */ /* The various kinds of lvalues we distinguish. */
......
...@@ -4507,8 +4507,10 @@ unqualified_namespace_lookup (tree name, int flags) ...@@ -4507,8 +4507,10 @@ unqualified_namespace_lookup (tree name, int flags)
} }
/* Look up NAME (an IDENTIFIER_NODE) in SCOPE (either a NAMESPACE_DECL /* 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 or a class TYPE).
bindings.
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 Returns a DECL (or OVERLOAD, or BASELINK) representing the
declaration found. If no suitable declaration can be found, declaration found. If no suitable declaration can be found,
...@@ -4516,28 +4518,25 @@ unqualified_namespace_lookup (tree name, int flags) ...@@ -4516,28 +4518,25 @@ unqualified_namespace_lookup (tree name, int flags)
neither a class-type nor a namespace a diagnostic is issued. */ neither a class-type nor a namespace a diagnostic is issued. */
tree 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) bool find_hidden)
{ {
int flags = 0;
tree t = NULL_TREE; tree t = NULL_TREE;
if (find_hidden)
flags |= LOOKUP_HIDDEN;
if (TREE_CODE (scope) == NAMESPACE_DECL) if (TREE_CODE (scope) == NAMESPACE_DECL)
{ {
struct scope_binding binding = EMPTY_SCOPE_BINDING; struct scope_binding binding = EMPTY_SCOPE_BINDING;
if (is_type_p) int flags = lookup_flags (prefer_type, /*namespaces_only*/false);
flags |= LOOKUP_PREFER_TYPES; if (find_hidden)
flags |= LOOKUP_HIDDEN;
if (qualified_lookup_using_namespace (name, scope, &binding, flags)) if (qualified_lookup_using_namespace (name, scope, &binding, flags))
t = binding.value; t = binding.value;
} }
else if (cxx_dialect != cxx98 && TREE_CODE (scope) == ENUMERAL_TYPE) else if (cxx_dialect != cxx98 && TREE_CODE (scope) == ENUMERAL_TYPE)
t = lookup_enumerator (scope, name); t = lookup_enumerator (scope, name);
else if (is_class_type (scope, complain)) 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) if (!t)
return error_mark_node; return error_mark_node;
......
...@@ -327,7 +327,7 @@ extern tree namespace_binding (tree, tree); ...@@ -327,7 +327,7 @@ extern tree namespace_binding (tree, tree);
extern void set_namespace_binding (tree, tree, tree); extern void set_namespace_binding (tree, tree, tree);
extern bool hidden_name_p (tree); extern bool hidden_name_p (tree);
extern tree remove_hidden_names (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_nonclass (tree);
extern tree lookup_name_innermost_nonclass_level (tree); extern tree lookup_name_innermost_nonclass_level (tree);
extern bool is_local_extern (tree); extern bool is_local_extern (tree);
......
...@@ -21190,7 +21190,7 @@ cp_parser_class_name (cp_parser *parser, ...@@ -21190,7 +21190,7 @@ cp_parser_class_name (cp_parser *parser,
resolution operator, object, function, and enumerator resolution operator, object, function, and enumerator
names are ignored. */ names are ignored. */
if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)) if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
tag_type = typename_type; tag_type = scope_type;
/* Look up the name. */ /* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier, decl = cp_parser_lookup_name (parser, identifier,
tag_type, tag_type,
...@@ -24595,6 +24595,24 @@ cp_parser_nested_requirement (cp_parser *parser) ...@@ -24595,6 +24595,24 @@ cp_parser_nested_requirement (cp_parser *parser)
/* Support Functions */ /* Support Functions */
/* Return the appropriate prefer_type argument for lookup_name_real based on
tag_type and template_mem_access. */
static inline int
prefer_type_arg (tag_types tag_type, bool template_mem_access = false)
{
/* DR 141: When looking in the current enclosing context for a template-name
after -> or ., only consider class templates. */
if (template_mem_access)
return 2;
switch (tag_type)
{
case none_type: return 0; // No preference.
case scope_type: return 1; // Type or namespace.
default: return 2; // Type only.
}
}
/* Looks up NAME in the current scope, as given by PARSER->SCOPE. /* Looks up NAME in the current scope, as given by PARSER->SCOPE.
NAME should have one of the representations used for an NAME should have one of the representations used for an
id-expression. If NAME is the ERROR_MARK_NODE, the ERROR_MARK_NODE id-expression. If NAME is the ERROR_MARK_NODE, the ERROR_MARK_NODE
...@@ -24731,7 +24749,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name, ...@@ -24731,7 +24749,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
errors may be issued. Even if we rollback the current errors may be issued. Even if we rollback the current
tentative parse, those errors are valid. */ tentative parse, those errors are valid. */
decl = lookup_qualified_name (parser->scope, name, decl = lookup_qualified_name (parser->scope, name,
tag_type != none_type, prefer_type_arg (tag_type),
/*complain=*/true); /*complain=*/true);
/* 3.4.3.1: In a lookup in which the constructor is an acceptable /* 3.4.3.1: In a lookup in which the constructor is an acceptable
...@@ -24752,7 +24770,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name, ...@@ -24752,7 +24770,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
&& DECL_SELF_REFERENCE_P (decl) && DECL_SELF_REFERENCE_P (decl)
&& same_type_p (DECL_CONTEXT (decl), parser->scope)) && same_type_p (DECL_CONTEXT (decl), parser->scope))
decl = lookup_qualified_name (parser->scope, ctor_identifier, decl = lookup_qualified_name (parser->scope, ctor_identifier,
tag_type != none_type, prefer_type_arg (tag_type),
/*complain=*/true); /*complain=*/true);
/* If we have a single function from a using decl, pull it out. */ /* If we have a single function from a using decl, pull it out. */
...@@ -24808,7 +24826,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name, ...@@ -24808,7 +24826,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
decl = lookup_member (object_type, decl = lookup_member (object_type,
name, name,
/*protect=*/0, /*protect=*/0,
tag_type != none_type, prefer_type_arg (tag_type),
tf_warning_or_error); tf_warning_or_error);
else else
decl = NULL_TREE; decl = NULL_TREE;
...@@ -24816,7 +24834,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name, ...@@ -24816,7 +24834,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
if (!decl) if (!decl)
/* Look it up in the enclosing context. DR 141: When looking for a /* Look it up in the enclosing context. DR 141: When looking for a
template-name after -> or ., only consider class templates. */ template-name after -> or ., only consider class templates. */
decl = lookup_name_real (name, tag_type != none_type || is_template, decl = lookup_name_real (name, prefer_type_arg (tag_type, is_template),
/*nonclass=*/0, /*nonclass=*/0,
/*block_p=*/true, is_namespace, 0); /*block_p=*/true, is_namespace, 0);
if (object_type == unknown_type_node) if (object_type == unknown_type_node)
...@@ -24828,7 +24846,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name, ...@@ -24828,7 +24846,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
} }
else else
{ {
decl = lookup_name_real (name, tag_type != none_type, decl = lookup_name_real (name, prefer_type_arg (tag_type),
/*nonclass=*/0, /*nonclass=*/0,
/*block_p=*/true, is_namespace, 0); /*block_p=*/true, is_namespace, 0);
parser->qualifying_scope = NULL_TREE; parser->qualifying_scope = NULL_TREE;
namespace A { }
namespace N { struct A; }
using namespace N;
struct ::A *p;
// PR c++/71173
namespace foo {
namespace bar {
class foo {};
}
class baz {};
}
using namespace foo::bar;
::foo::baz mybaz;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment