aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/name-lookup.c15
-rw-r--r--gcc/cp/name-lookup.h2
-rw-r--r--gcc/testsuite/g++.dg/lookup/friend17.C9
4 files changed, 30 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 743e059..90c76ff 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2016-02-16 Jason Merrill <jason@redhat.com>
+
+ PR c++/69657
+ * name-lookup.c (lookup_qualified_name): Add find_hidden parm.
+ (set_decl_namespace): Pass it. Complain about finding a hidden friend.
+ * name-lookup.h: Adjust.
+
2016-02-16 James Norris <jnorris@codesourcery.com>
* parser.c (cp_parser_oacc_data_clause_deviceptr): Remove checking.
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index b5961e5..b73f3f7 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3502,7 +3502,8 @@ set_decl_namespace (tree decl, tree scope, bool friendp)
}
/* See whether this has been declared in the namespace. */
- old = lookup_qualified_name (scope, DECL_NAME (decl), false, true);
+ old = lookup_qualified_name (scope, DECL_NAME (decl), /*type*/false,
+ /*complain*/true, /*hidden*/true);
if (old == error_mark_node)
/* No old declaration at all. */
goto complain;
@@ -3565,6 +3566,12 @@ set_decl_namespace (tree decl, tree scope, bool friendp)
{
if (!is_associated_namespace (scope, CP_DECL_CONTEXT (found)))
goto complain;
+ if (DECL_HIDDEN_FRIEND_P (found))
+ {
+ pedwarn (DECL_SOURCE_LOCATION (decl), 0,
+ "%qD has not been declared within %D", decl, scope);
+ inform (DECL_SOURCE_LOCATION (found), "only here as a friend");
+ }
DECL_CONTEXT (decl) = DECL_CONTEXT (found);
return;
}
@@ -4509,11 +4516,15 @@ 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, bool is_type_p, 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;
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index bce12bb..7e39b6c 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);
+extern tree lookup_qualified_name (tree, tree, bool, 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/testsuite/g++.dg/lookup/friend17.C b/gcc/testsuite/g++.dg/lookup/friend17.C
new file mode 100644
index 0000000..46b6be5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/friend17.C
@@ -0,0 +1,9 @@
+// PR c++/69657
+// { dg-options "-Wpedantic" }
+
+namespace N {
+ struct A {
+ friend void f(A);
+ };
+}
+void N::f(A) { } // { dg-warning "declared" }