From: Anthony Sharp <anthonysharp15@gmail.com>
To: Jason Merrill <jason@redhat.com>
Cc: gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] c++: private inheritance access diagnostics fix [PR17314]
Date: Sat, 9 Jan 2021 00:38:23 +0000 [thread overview]
Message-ID: <CA+Lh_Am9G=N4eh-UeX_RHwrCO024Y2MHmp22-9qv1W1ixw0J=A@mail.gmail.com> (raw)
In-Reply-To: <8beca582-97eb-3e4c-1437-162ae896f031@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 4273 bytes --]
Hi Jason,
Thank you!
> To start with, do you have a copyright assignment on file or in the
> works already?
Good point. I incorrectly assumed it would only be a minor
contribution copyright-wise. Mr Edelsohn gave me a template which I've
now filled out and sent to assign@gnu.org. I'm assuming I just need to
wait for them to send me the form. I'll update this thread when that's
sorted. In the meantime I've hopefully fixed some of the issues.
> Second, your patch was mangled by word wrap so that it can't be applied
> without manual repair. If you can't prevent word wrap in your mail
> client, please send it as an attachment rather than inline.
Oh yes I see where it's gotten mangled now. I'm attaching it as a
.patch file (I assume that's okay).
> Also, there are a few whitespace issues in the patch; please run
> contrib/check_GNU_style.sh on the patch before submitting.
Should be all fixed now (there is one style issue left but it's a
false positive). Visual Studio Code was lying to me about what the
file looks like so if there are any more formatting issues please let
me know.
> If you use contrib/gcc-git-customization.sh and then git
> gcc-commit-mklog you don't need to touch ChangeLog files at all, just
> adjust the generated ChangeLog entries in the git commit message. I
> personally tend to commit first with a placeholder message and then use
> git gcc-commit-mklog --amend to generate the ChangeLog entries.
Wouldn't that require read-write access? (Just from looking here
https://gcc.gnu.org/gitwrite.html.)
> Probably. Can you use sort/uniq/diff on the .sum testsuite output to
> determine which passes are missing in the patched sources?
According to contrib/dg-cmp-results.sh ...
I get a bunch of these weird NA->PASSes (and vice-versa), for example:
PASS->NA: g++.dg/modules/alias-1_a.H module-cmi
(gcm.cache/home/anthony/Desktop/GCC/builds_and_source/source_clean/gcc/testsuite/g++.dg/modules/alias-1_a.H.gcm)
NA->PASS: g++.dg/modules/alias-1_a.H module-cmi
(gcm.cache/home/anthony/Desktop/GCC/builds_and_source/source_pr17314/gcc/testsuite/g++.dg/modules/alias-1_a.H.gcm)
PASS->NA: g++.dg/modules/alias-1_a.H module-cmi
(gcm.cache/home/anthony/Desktop/GCC/builds_and_source/source_clean/gcc/testsuite/g++.dg/modules/alias-1_a.H.gcm)
NA->PASS: g++.dg/modules/alias-1_a.H module-cmi
(gcm.cache/home/anthony/Desktop/GCC/builds_and_source/source_pr17314/gcc/testsuite/g++.dg/modules/alias-1_a.H.gcm)
They're weird because I haven't actually touched those files (so I'm
assuming this is normal). There are about ~400 of those and they're
all .gcm files. They seem to balance out.
dr142.c reports:
NA->PASS: g++.dg/tc1/dr142.C -std=c++14 (test for warnings, line 11)
PASS->NA: g++.dg/tc1/dr142.C -std=c++14 (test for warnings, line 5)
PASS->NA: g++.dg/tc1/dr142.C -std=c++14 (test for warnings, line 7)
PASS->NA: g++.dg/tc1/dr142.C -std=c++14 (test for warnings, line 8)
NA->PASS: g++.dg/tc1/dr142.C -std=c++17 (test for warnings, line 11)
PASS->NA: g++.dg/tc1/dr142.C -std=c++17 (test for warnings, line 5)
PASS->NA: g++.dg/tc1/dr142.C -std=c++17 (test for warnings, line 7)
PASS->NA: g++.dg/tc1/dr142.C -std=c++17 (test for warnings, line 8)
NA->PASS: g++.dg/tc1/dr142.C -std=c++2a (test for warnings, line 11)
PASS->NA: g++.dg/tc1/dr142.C -std=c++2a (test for warnings, line 5)
PASS->NA: g++.dg/tc1/dr142.C -std=c++2a (test for warnings, line 7)
PASS->NA: g++.dg/tc1/dr142.C -std=c++2a (test for warnings, line 8)
NA->PASS: g++.dg/tc1/dr142.C -std=c++98 (test for warnings, line 11)
PASS->NA: g++.dg/tc1/dr142.C -std=c++98 (test for warnings, line 5)
PASS->NA: g++.dg/tc1/dr142.C -std=c++98 (test for warnings, line 7)
PASS->NA: g++.dg/tc1/dr142.C -std=c++98 (test for warnings, line 8)
In other words, there are 12 PASS->NAs and 4 NA->PASSes in this file,
meaning a net change of -8 (which explains why there are eight fewer).
My other changes also report PASS->NAs and vice-versa, but for those
the number of new NAs equals the number of new PASSes, so they don't
cause a change in quantity.
Thanks for being patient with me. I'll let you know when I've
completed the forms.
Also if I need to adjust the .patch to deal with the changelogs issue
please let me know.
Kind regards,
Anthony
[-- Attachment #2: pr17314.patch --]
[-- Type: text/x-patch, Size: 15991 bytes --]
Index: gcc/testsuite/g++.old-deja/g++.jason/access8.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.jason/access8.C 2020-12-31 16:51:34.000000000 +0000
+++ gcc/testsuite/g++.old-deja/g++.jason/access8.C 2021-01-03 00:22:14.969854000 +0000
@@ -4,5 +4,5 @@
// Bug: g++ forgets access decls after the definition.
-class inh { // { dg-message "" } inaccessible
+class inh {
int a;
protected:
@@ -10,5 +10,6 @@ protected:
};
-class mel : private inh {
+class mel : private inh // { dg-message "" } inaccessible
+{
protected:
int t;
Index: gcc/testsuite/g++.old-deja/g++.law/access4.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.law/access4.C 2020-12-31 16:51:34.000000000 +0000
+++ gcc/testsuite/g++.old-deja/g++.law/access4.C 2021-01-03 00:21:01.736320000 +0000
@@ -7,10 +7,11 @@
// Message-ID: <9403030024.AA04534@ses.com>
-class ForceLeafSterile { // { dg-message "" }
+class ForceLeafSterile {
friend class Sterile;
ForceLeafSterile() {} // { dg-message "" }
};
-class Sterile : private virtual ForceLeafSterile {
+class Sterile : private virtual ForceLeafSterile // { dg-message "" }
+{
public:
Sterile() {}
Index: gcc/testsuite/g++.old-deja/g++.law/visibility12.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.law/visibility12.C 2020-12-31 16:51:34.000000000 +0000
+++ gcc/testsuite/g++.old-deja/g++.law/visibility12.C 2021-01-03 00:20:24.243535000 +0000
@@ -7,9 +7,10 @@
// Message-ID: <9306300528.AA17185@coda.mel.dit.CSIRO.AU>
struct a {
- int aa; // { dg-message "" } private
+ int aa;
};
-class b : private a {
- };
+class b : private a // { dg-message "" } private
+{
+};
class c : public b {
Index: gcc/testsuite/g++.old-deja/g++.law/visibility8.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.law/visibility8.C 2020-12-31 16:51:34.000000000 +0000
+++ gcc/testsuite/g++.old-deja/g++.law/visibility8.C 2021-01-03 00:19:45.574725000 +0000
@@ -8,9 +8,10 @@
class t1 {
protected:
- int a; // { dg-message "" } protected
+ int a;
};
-class t2 : private t1 {
+class t2 : private t1 // { dg-message "" } protected
+{
public:
int b;
Index: gcc/testsuite/g++.old-deja/g++.law/visibility4.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.law/visibility4.C 2020-12-31 16:51:34.000000000 +0000
+++ gcc/testsuite/g++.old-deja/g++.law/visibility4.C 2021-01-03 00:20:06.815170000 +0000
@@ -9,8 +9,9 @@
class A {
public:
- int b; // { dg-message "" } private
+ int b;
};
-class C : private A { // NOTE WELL. private, not public
+class C : private A // { dg-message "" } private
+{
public:
int d;
Index: gcc/testsuite/g++.old-deja/g++.other/access4.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.other/access4.C 2020-12-31 16:51:34.000000000 +0000
+++ gcc/testsuite/g++.old-deja/g++.other/access4.C 2021-01-03 00:19:25.362302000 +0000
@@ -1,9 +1,9 @@
// { dg-do assemble }
-struct A { // { dg-message "" } inaccessible
+struct A {
static int i;
};
-struct B : private A { };
+struct B : private A { }; // { dg-message "" } inaccessible
struct C : public B {
Index: gcc/testsuite/g++.old-deja/g++.brendan/visibility8.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.brendan/visibility8.C 2020-12-31 16:51:34.000000000 +0000
+++ gcc/testsuite/g++.old-deja/g++.brendan/visibility8.C 2021-01-03 00:19:17.918146000 +0000
@@ -6,7 +6,7 @@ class foo
{
public:
- static int y; // { dg-message "" } private
+ static int y;
};
-class foo1 : private foo
+class foo1 : private foo // { dg-message "" } private
{ };
class foo2 : public foo1
Index: gcc/testsuite/g++.old-deja/g++.brendan/visibility6.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.brendan/visibility6.C 2020-12-31 16:51:34.000000000 +0000
+++ gcc/testsuite/g++.old-deja/g++.brendan/visibility6.C 2021-01-03 00:21:55.873454000 +0000
@@ -4,7 +4,7 @@ class bottom
{
public:
- int b; // { dg-message "" } private
+ int b;
};
-class middle : private bottom
+class middle : private bottom // { dg-message "" } private
{
public:
Index: gcc/testsuite/g++.dg/lookup/scoped1.C
===================================================================
--- gcc/testsuite/g++.dg/lookup/scoped1.C 2020-12-31 16:51:34.000000000 +0000
+++ gcc/testsuite/g++.dg/lookup/scoped1.C 2021-01-02 21:51:30.088674000 +0000
@@ -5,10 +5,10 @@ struct A
{
static int i1;
- int i2; // { dg-message "declared" }
+ int i2;
static void f1 ();
void f2 ();
};
-struct B: private A { };
+struct B: private A { }; // { dg-message "declared" }
struct C: public B
{
Index: gcc/testsuite/g++.dg/tc1/dr142.C
===================================================================
--- gcc/testsuite/g++.dg/tc1/dr142.C 2020-12-31 16:51:34.000000000 +0000
+++ gcc/testsuite/g++.dg/tc1/dr142.C 2021-01-02 21:54:09.839546000 +0000
@@ -3,11 +3,11 @@
// DR142: Injection-related errors in access example
-class B { // { dg-message "declared" }
+class B {
public:
- int mi; // { dg-message "declared" }
- static int si; // { dg-message "declared" }
+ int mi;
+ static int si;
};
-class D: private B {
+class D: private B { // { dg-message "declared" }
};
Index: gcc/testsuite/g++.dg/tc1/dr52.C
===================================================================
--- gcc/testsuite/g++.dg/tc1/dr52.C 2020-12-31 16:51:34.000000000 +0000
+++ gcc/testsuite/g++.dg/tc1/dr52.C 2021-01-03 13:20:08.267946000 +0000
@@ -18,9 +18,9 @@ struct B2 : B {};
struct C
-{ // { dg-message "declared" }
- void foo(void);
+{
+ void foo(void);
};
-struct D : private C {};
+struct D : private C {}; // { dg-message "declared" }
struct X: A, B1, B2, D
Index: gcc/testsuite/ChangeLog
from Anthony Sharp <anthonysharp15@gmail.com>
Fixes PR17314
* g++.dg/lookup/scoped1.c modified testcase to run successfully with
changes.
* g++.dg/tc1/dr142.c modified testcase to run successfully with
changes.
* g++.dg/tc1/dr142.c modified testcase to run successfully with
changes.
* g++.dg/tc1/dr142.c modified testcase to run successfully with
changes.
* g++.dg/tc1/dr52.c modified testcase to run successfully with changes.
* g++.old-deja/g++.brendan/visibility6.c modified testcase to run
successfully with changes.
* g++.old-deja/g++.brendan/visibility8.c modified testcase to run
successfully with changes.
* g++.old-deja/g++.jason/access8.c modified testcase to run
successfully with changes.
* g++.old-deja/g++.law/access4.c modified testcase to run successfully
with changes.
* g++.old-deja/g++.law/visibility12.c modified testcase to run
successfully with changes.
* g++.old-deja/g++.law/visibility4.c modified testcase to run
successfully with changes.
* g++.old-deja/g++.law/visibility8.c modified testcase to run
successfully with changes.
* g++.old-deja/g++.other/access4.c modified testcase to run
successfully with changes.
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c 2020-12-31 16:51:34.000000000 +0000
+++ gcc/cp/semantics.c 2021-01-09 00:03:36.308446274 +0000
@@ -47,4 +47,6 @@ along with GCC; see the file COPYING3.
#include "memmodel.h"
+extern access_kind access_in_type (tree type, tree decl);
+
/* There routines provide a modular interface to perform many parsing
operations. They may therefore be used during actual parsing, or
@@ -257,4 +259,39 @@ pop_to_parent_deferring_access_checks (v
}
+/* This deals with bug PR17314.
+
+ DECL is a declaration and BINFO represents a class that has attempted (but
+ failed) to access DECL.
+
+ Examine the parent binfos of BINFO and determine whether any of them had
+ private access to DECL. If they did, return the parent binfo. This helps
+ in figuring out the correct error message to show (if the parents had
+ access, it's their fault for not giving sufficient access to BINFO).
+
+ If no parents had access, return NULL_TREE. */
+
+static tree
+get_parent_with_private_access (tree decl, tree binfo)
+{
+ /* Only BINFOs should come through here. */
+ gcc_assert (TREE_CODE (binfo) == TREE_BINFO);
+
+ tree base_binfo = NULL_TREE;
+
+ /* Iterate through immediate parent classes. */
+ for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ {
+ /* This parent had private access. Therefore that's why BINFO can't
+ access DECL. */
+ if (access_in_type (BINFO_TYPE (base_binfo), decl) == ak_private)
+ return base_binfo;
+ }
+
+ /* None of the parents had access. Note: it's impossible for one of the
+ parents to have had public or protected access to DECL, since then
+ BINFO would have been able to access DECL too. */
+ return NULL_TREE;
+}
+
/* If the current scope isn't allowed to access DECL along
BASETYPE_PATH, give an error, or if we're parsing a function or class
@@ -315,9 +352,38 @@ enforce_access (tree basetype_path, tree
{
if (flag_new_inheriting_ctors)
- diag_decl = strip_inheriting_ctors (diag_decl);
+ 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);
+ afi->record_access_failure (basetype_path, decl, diag_decl);
return false;
}
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h 2020-12-31 16:51:34.000000000 +0000
+++ gcc/cp/cp-tree.h 2021-01-08 22:45:02.106467958 +0000
@@ -6435,5 +6435,6 @@ class access_failure_info
};
-extern void complain_about_access (tree, tree, bool);
+extern void complain_about_access (tree, tree, tree, bool,
+ access_kind);
extern void push_defarg_context (tree);
extern void pop_defarg_context (void);
Index: gcc/cp/search.c
===================================================================
--- gcc/cp/search.c 2020-12-31 16:51:34.000000000 +0000
+++ gcc/cp/search.c 2021-01-01 01:33:56.788180000 +0000
@@ -48,5 +48,5 @@ static tree dfs_walk_once_accessible (tr
void *data);
static tree dfs_access_in_type (tree, void *);
-static access_kind access_in_type (tree, tree);
+access_kind access_in_type (tree, tree);
static tree dfs_get_pure_virtuals (tree, void *);
@@ -584,5 +584,5 @@ dfs_access_in_type (tree binfo, void *da
/* Return the access to DECL in TYPE. */
-static access_kind
+access_kind
access_in_type (tree type, tree decl)
{
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c 2020-12-31 16:51:34.000000000 +0000
+++ gcc/cp/typeck.c 2021-01-01 01:37:13.602815000 +0000
@@ -2981,5 +2981,6 @@ complain_about_unrecognized_member (tree
? TREE_TYPE (access_path) : object_type,
name, afi.get_diag_decl ());
- complain_about_access (afi.get_decl (), afi.get_diag_decl (), false);
+ complain_about_access (afi.get_decl (), afi.get_diag_decl (),
+ afi.get_diag_decl (), false, ak_none);
}
}
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c 2020-12-31 16:51:34.000000000 +0000
+++ gcc/cp/call.c 2021-01-09 00:08:05.249597968 +0000
@@ -7133,31 +7133,49 @@ build_op_delete_call (enum tree_code cod
in the diagnostics.
- If ISSUE_ERROR is true, then issue an error about the
- access, followed by a note showing the declaration.
- Otherwise, just show the note. */
+ If ISSUE_ERROR is true, then issue an error about the access, followed
+ by a note showing the declaration. Otherwise, just show the note.
+
+ DIAG_DECL and DIAG_LOCATION will almost always be the same.
+ DIAG_LOCATION is just another DECL. NO_ACCESS_REASON is an optional
+ parameter used to specify why DECL wasn't accessible (e.g. ak_private
+ would be because DECL was private). If not using NO_ACCESS_REASON,
+ then it must be ak_none, and the access failure reason will be
+ figured out by looking at the protection of DECL. */
void
-complain_about_access (tree decl, tree diag_decl, bool issue_error)
+complain_about_access (tree decl, tree diag_decl, tree diag_location,
+bool issue_error, access_kind no_access_reason)
{
- if (TREE_PRIVATE (decl))
- {
- if (issue_error)
- error ("%q#D is private within this context", diag_decl);
- inform (DECL_SOURCE_LOCATION (diag_decl),
- "declared private here");
- }
- else if (TREE_PROTECTED (decl))
- {
- if (issue_error)
- error ("%q#D is protected within this context", diag_decl);
- inform (DECL_SOURCE_LOCATION (diag_decl),
- "declared protected here");
- }
+ /* If we have not already figured out why DECL is innaccessible... */
+ if (no_access_reason == ak_none)
+ {
+ /* Examine the access of DECL to find out why. */
+ if (TREE_PRIVATE (decl))
+ no_access_reason = ak_private;
+ else if (TREE_PROTECTED (decl))
+ no_access_reason = ak_protected;
+ }
+
+ /* Now generate an error message depending on calculated access. */
+ if (no_access_reason == ak_private)
+ {
+ if (issue_error)
+ error ("%q#D is private within this context", diag_decl);
+ inform (DECL_SOURCE_LOCATION (diag_location), "declared private here");
+ }
+ else if (no_access_reason == ak_protected)
+ {
+ if (issue_error)
+ error ("%q#D is protected within this context", diag_decl);
+ inform (DECL_SOURCE_LOCATION (diag_location), "declared protected here");
+ }
+ /* Couldn't figure out why DECL is innaccesible, so just say it's
+ innaccessible. */
else
- {
- if (issue_error)
- error ("%q#D is inaccessible within this context", diag_decl);
- inform (DECL_SOURCE_LOCATION (diag_decl), "declared here");
- }
+ {
+ if (issue_error)
+ error ("%q#D is inaccessible within this context", diag_decl);
+ inform (DECL_SOURCE_LOCATION (diag_decl), "declared here");
+ }
}
Index: gcc/cp/ChangeLog
from Anthony Sharp <anthonysharp15@gmail.com>
Fixes PR17314
* typeck.c (complain_about_unrecognized_member): Updated function
arguments in complain_about_access.
* call.c (complain_about_access): Altered function.
* semantics.c (get_parent_with_private_access): Added function.
(access_in_type): Added as extern function.
* search.c (access_in_type): Made function non-static so it can be
used in semantics.c.
* cp-tree.h (complain_about_access): Changed parameters of function.
next prev parent reply other threads:[~2021-01-09 0:39 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-05 14:24 Anthony Sharp
2021-01-07 21:01 ` Jason Merrill
2021-01-09 0:38 ` Anthony Sharp [this message]
2021-01-11 20:03 ` Jason Merrill
2021-01-21 19:28 ` Anthony Sharp
2021-01-21 22:56 ` Jason Merrill
2021-01-22 3:44 ` Jason Merrill
2021-01-22 20:07 ` Anthony Sharp
2021-01-22 21:18 ` Jason Merrill
2021-01-22 22:36 ` Anthony Sharp
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CA+Lh_Am9G=N4eh-UeX_RHwrCO024Y2MHmp22-9qv1W1ixw0J=A@mail.gmail.com' \
--to=anthonysharp15@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jason@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).