From 1b22fc54fd4fe739ba2d223fc8f3e3b036beddf1 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 25 May 2016 14:29:14 -0400 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 12 +++++++++++ gcc/cp/cp-tree.h | 3 ++- gcc/cp/name-lookup.c | 19 ++++++++-------- gcc/cp/name-lookup.h | 2 +- gcc/cp/parser.c | 30 ++++++++++++++++++++------ gcc/testsuite/g++.dg/lookup/scoped10.C | 5 +++++ gcc/testsuite/g++.dg/lookup/scoped9.C | 10 +++++++++ 7 files changed, 63 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/scoped10.C create mode 100644 gcc/testsuite/g++.dg/lookup/scoped9.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9f618a4f2ff..f0cd5d9abc0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2016-05-25 Jason Merrill + + 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 * parser.c (cp_parser_oacc_declare): Add support for diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ad21cdf8334..c2be21c7424 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 d32a1532e1a..eb128db5733 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, &binding, 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 7e39b6c92e0..2f8447a64c7 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 d21230fdd8d..546aada5156 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) /* 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. NAME should have one of the representations used for an 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, errors may be issued. Even if we rollback the current tentative parse, those errors are valid. */ decl = lookup_qualified_name (parser->scope, name, - tag_type != none_type, + prefer_type_arg (tag_type), /*complain=*/true); /* 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, && DECL_SELF_REFERENCE_P (decl) && same_type_p (DECL_CONTEXT (decl), parser->scope)) decl = lookup_qualified_name (parser->scope, ctor_identifier, - tag_type != none_type, + prefer_type_arg (tag_type), /*complain=*/true); /* 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, decl = lookup_member (object_type, name, /*protect=*/0, - tag_type != none_type, + prefer_type_arg (tag_type), tf_warning_or_error); else decl = NULL_TREE; @@ -24816,7 +24834,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name, if (!decl) /* Look it up in the enclosing context. DR 141: When looking for a 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, /*block_p=*/true, is_namespace, 0); if (object_type == unknown_type_node) @@ -24828,7 +24846,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name, } else { - decl = lookup_name_real (name, tag_type != none_type, + decl = lookup_name_real (name, prefer_type_arg (tag_type), /*nonclass=*/0, /*block_p=*/true, is_namespace, 0); parser->qualifying_scope = NULL_TREE; diff --git a/gcc/testsuite/g++.dg/lookup/scoped10.C b/gcc/testsuite/g++.dg/lookup/scoped10.C new file mode 100644 index 00000000000..c604297c6db --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/scoped10.C @@ -0,0 +1,5 @@ +namespace A { } +namespace N { struct A; } +using namespace N; + +struct ::A *p; diff --git a/gcc/testsuite/g++.dg/lookup/scoped9.C b/gcc/testsuite/g++.dg/lookup/scoped9.C new file mode 100644 index 00000000000..06f09028b0a --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/scoped9.C @@ -0,0 +1,10 @@ +// PR c++/71173 + +namespace foo { + namespace bar { + class foo {}; + } + class baz {}; +} +using namespace foo::bar; +::foo::baz mybaz; -- 2.30.2