Friend accessibility check is wrong when at least 2-step inheritance is
present. Friendship check is done with the currently observed base instead of
the class for which the check is actually requested. This patch fixes that
issue.

PR c++/123228

gcc/cp/ChangeLog:

        * search.cc (dfs_walk_once_accessible_r): Pass lookup initiation binfo 
as a separate
        parameter.

gcc/testsuite/ChangeLog:

        * g++.dg/lookup/friend26.C: New test.

Tested on x86_64-pc-linux-gnu.
---
 gcc/cp/search.cc                       | 11 ++++++-----
 gcc/testsuite/g++.dg/lookup/friend26.C | 23 +++++++++++++++++++++++
 2 files changed, 29 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/lookup/friend26.C

diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc
index 77b5b1da5..880e97639 100644
--- a/gcc/cp/search.cc
+++ b/gcc/cp/search.cc
@@ -1634,7 +1634,8 @@ dfs_walk_once (tree binfo, tree (*pre_fn) (tree, void *),
    indicates whether bases should be marked during traversal.  */
 
 static tree
-dfs_walk_once_accessible_r (tree binfo, bool friends_p, hash_set<tree> *pset,
+dfs_walk_once_accessible_r (tree binfo, tree binfo_initial, bool friends_p,
+                           hash_set<tree> *pset,
                            tree (*pre_fn) (tree, void *),
                            tree (*post_fn) (tree, void *), void *data)
 {
@@ -1674,15 +1675,15 @@ dfs_walk_once_accessible_r (tree binfo, bool friends_p, 
hash_set<tree> *pset,
          scope = current_scope ();
          if (!scope
              || TREE_CODE (scope) == NAMESPACE_DECL
-             || !is_friend (BINFO_TYPE (binfo), scope))
+             || !is_friend (BINFO_TYPE (binfo_initial), scope))
            continue;
        }
 
       if (mark)
        pset->add (base_binfo);
 
-      rval = dfs_walk_once_accessible_r (base_binfo, friends_p, pset,
-                                        pre_fn, post_fn, data);
+      rval = dfs_walk_once_accessible_r (base_binfo, binfo_initial, friends_p,
+                                  pset, pre_fn, post_fn, data);
       if (rval)
        return rval;
     }
@@ -1711,7 +1712,7 @@ dfs_walk_once_accessible (tree binfo, bool friends_p,
   hash_set<tree> *pset = NULL;
   if (CLASSTYPE_DIAMOND_SHAPED_P (BINFO_TYPE (binfo)))
     pset = new hash_set<tree>;
-  tree rval = dfs_walk_once_accessible_r (binfo, friends_p, pset,
+  tree rval = dfs_walk_once_accessible_r (binfo, binfo, friends_p, pset,
                                          pre_fn, post_fn, data);
 
   if (pset)
diff --git a/gcc/testsuite/g++.dg/lookup/friend26.C 
b/gcc/testsuite/g++.dg/lookup/friend26.C
new file mode 100644
index 000000000..ffc422909
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/friend26.C
@@ -0,0 +1,23 @@
+// PR c++/123228
+
+struct A {
+    friend struct C;
+
+    A() : i(0) {}
+private:
+    int i;
+};
+
+struct B : protected A {
+};
+
+struct C : B {
+    void f() {    
+        i = 1;
+    }
+};
+
+void foo() {
+    C c;
+    c.f();
+}
-- 
2.53.0

Reply via email to