Re: C++ PATCH for c++/70522 (friend hides name in unnamed namespace)

2016-05-25 Thread Jason Merrill

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)
 

C++ PATCH for c++/70522 (friend hides name in unnamed namespace)

2016-04-19 Thread Jason Merrill
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.


Tested x86_64-pc-linux-gnu, applying to trunk.
commit 995a41f6f9153cbc4ec713ec645a3edebc408ec2
Author: Jason Merrill 
Date:   Tue Apr 19 09:11:38 2016 -0400

	PR c++/70522

	* name-lookup.c (qualified_lookup_using_namespace): Look through
	hidden names.

diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 89d84d7..b3828c0 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -4647,8 +4647,9 @@ qualified_lookup_using_namespace (tree name, tree scope,
 	cp_binding_level_find_binding_for_name (NAMESPACE_LEVEL (scope), name);
 	  if (binding)
 	{
-	  found_here = true;
 	  ambiguous_decl (result, binding, flags);
+	  if (result->type || result->value)
+		found_here = true;
 	}
 
 	  for (usings = DECL_NAMESPACE_USING (scope); usings;
diff --git a/gcc/testsuite/g++.dg/lookup/friend18.C b/gcc/testsuite/g++.dg/lookup/friend18.C
new file mode 100644
index 000..90cd2d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/friend18.C
@@ -0,0 +1,15 @@
+// PR c++/70522
+
+namespace A {
+  struct C {
+friend void i();
+  };
+  namespace {
+int i;
+  }
+}
+
+int main()
+{
+  return A::i;
+}