aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2016-05-25 18:29:14 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2016-05-25 18:29:14 +0000
commit6860a44898978059f7705485cd358edc29f84976 (patch)
tree0cd1bfde15477ae2028496320a01fa745b2ca052
parenta322d8dcb9e958f43fbf285968633a4e0fd2b582 (diff)
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@236736 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/name-lookup.c19
-rw-r--r--gcc/cp/name-lookup.h2
-rw-r--r--gcc/cp/parser.c30
-rw-r--r--gcc/testsuite/g++.dg/lookup/scoped10.C5
-rw-r--r--gcc/testsuite/g++.dg/lookup/scoped9.C10
7 files changed, 63 insertions, 18 deletions
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 <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>
* 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;