aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/semantics.c
diff options
context:
space:
mode:
authorAnthony Sharp <anthonysharp15@gmail.com>2021-01-22 22:36:06 +0000
committerJason Merrill <jason@redhat.com>2021-01-23 17:48:31 -0500
commit7e0f147a29f42d6149585573650bd4827f3b2b93 (patch)
treea852452165cc39e93ebf00c3de49a1158aae09ae /gcc/cp/semantics.c
parentc63f091db89a56ae56b2bfa2ba4d9e956bd9693f (diff)
downloadgcc-7e0f147a29f42d6149585573650bd4827f3b2b93.zip
gcc-7e0f147a29f42d6149585573650bd4827f3b2b93.tar.gz
gcc-7e0f147a29f42d6149585573650bd4827f3b2b93.tar.bz2
c++: private inheritance access diagnostics fix [PR17314]
This patch fixes PR17314. Previously, when class C attempted to access member a declared in class A through class B, where class B privately inherits from A and class C inherits from B, GCC would correctly report an access violation, but would erroneously report that the reason was because a was "protected", when in fact, from the point of view of class C, it was really "private". This patch updates the diagnostics code to generate more correct errors in cases of failed inheritance such as these. The reason this bug happened was because GCC was examining the declared access of decl, instead of looking at it in the context of class inheritance. gcc/cp/ChangeLog: 2021-01-21 Anthony Sharp <anthonysharp15@gmail.com> * call.c (complain_about_access): Altered function. * cp-tree.h (complain_about_access): Changed parameters of function. (get_parent_with_private_access): Declared new function. * search.c (get_parent_with_private_access): Defined new function. * semantics.c (enforce_access): Modified function. * typeck.c (complain_about_unrecognized_member): Updated function arguments in complain_about_access. gcc/testsuite/ChangeLog: 2021-01-21 Anthony Sharp <anthonysharp15@gmail.com> * g++.dg/lookup/scoped1.C: Modified testcase to run successfully with changes. * g++.dg/tc1/dr142.C: Same as above. * g++.dg/tc1/dr52.C: Same as above. * g++.old-deja/g++.brendan/visibility6.C: Same as above. * g++.old-deja/g++.brendan/visibility8.C: Same as above. * g++.old-deja/g++.jason/access8.C: Same as above. * g++.old-deja/g++.law/access4.C: Same as above. * g++.old-deja/g++.law/visibility12.C: Same as above. * g++.old-deja/g++.law/visibility4.C: Same as above. * g++.old-deja/g++.law/visibility8.C: Same as above. * g++.old-deja/g++.other/access4.C: Same as above.
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r--gcc/cp/semantics.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 51841dc..7383446 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -316,7 +316,36 @@ enforce_access (tree basetype_path, tree decl, tree diag_decl,
if (flag_new_inheriting_ctors)
diag_decl = strip_inheriting_ctors (diag_decl);
if (complain & tf_error)
- complain_about_access (decl, diag_decl, true);
+ {
+ /* We will usually want to point to the same place as
+ diag_decl but not always. */
+ tree diag_location = diag_decl;
+ access_kind parent_access = ak_none;
+
+ /* See if any of BASETYPE_PATH's parents had private access
+ to DECL. If they did, that will tell us why we don't. */
+ tree parent_binfo = get_parent_with_private_access (decl,
+ basetype_path);
+
+ /* If a parent had private access, then the diagnostic
+ location DECL should be that of the parent class, since it
+ failed to give suitable access by using a private
+ inheritance. But if DECL was actually defined in the parent,
+ it wasn't privately inherited, and so we don't need to do
+ this, and complain_about_access will figure out what to
+ do. */
+ if (parent_binfo != NULL_TREE
+ && (context_for_name_lookup (decl)
+ != BINFO_TYPE (parent_binfo)))
+ {
+ diag_location = TYPE_NAME (BINFO_TYPE (parent_binfo));
+ parent_access = ak_private;
+ }
+
+ /* Finally, generate an error message. */
+ complain_about_access (decl, diag_decl, diag_location, true,
+ parent_access);
+ }
if (afi)
afi->record_access_failure (basetype_path, decl, diag_decl);
return false;