/* Issue diagnostics about a disallowed access of DECL, using DIAG_DECL
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 we have not already figured out why DECL is inaccessible... */
+ 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_decl),
- "declared private here");
+ inform (DECL_SOURCE_LOCATION (diag_location), "declared private here");
}
- else if (TREE_PROTECTED (decl))
+ 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_decl),
- "declared protected here");
+ inform (DECL_SOURCE_LOCATION (diag_location), "declared protected here");
}
+ /* Couldn't figure out why DECL is inaccesible, so just say it's
+ inaccessible. */
else
{
if (issue_error)
tree m_diag_decl;
};
-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);
extern tree convert_default_arg (tree, tree, tree, int,
extern tree get_pseudo_tinfo_type (unsigned);
/* in search.c */
+extern tree get_parent_with_private_access (tree decl, tree binfo);
extern bool accessible_base_p (tree, tree, bool);
extern tree lookup_base (tree, tree, base_access,
base_kind *, tsubst_flags_t);
return NULL_TREE;
}
+/* 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. */
+
+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;
+}
+
/* Returns true if type BASE is accessible in T. (BASE is known to be
a (possibly non-proper) base class of T.) If CONSIDER_LOCAL_P is
true, consider any special access of the current scope, or access
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;
TREE_CODE (access_path) == TREE_BINFO
? 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);
}
}
else
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
{
void g ()
// Origin: Giovanni Bajo <giovannibajo at gcc dot gnu dot org>
// 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" }
};
class DD: public D {
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
{
class bottom
{
public:
- int b; // { dg-message "" } private
+ int b;
};
-class middle : private bottom
+class middle : private bottom // { dg-message "" } private
{
public:
void foo () { b; }
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
{ public:
// Date: 25 Jan 1994 23:41:33 -0500
// Bug: g++ forgets access decls after the definition.
-class inh { // { dg-message "" } inaccessible
+class inh {
int a;
protected:
void myf(int);
};
-class mel : private inh {
+class mel : private inh // { dg-message "" } inaccessible
+{
protected:
int t;
inh::myf; // { dg-warning "deprecated" }
// Subject: g++ 2.5.5 doesn't warn about inaccessible virtual base ctor
// 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() {}
Sterile(const char* /*blah*/) {}
// Subject: member access rule bug
// 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 {
int xx(void) { return (aa); } // aa should be invisible// { dg-error "" } .*
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;
};
// Message-ID: <m0nof3E-0021ifC@jts.com
class t1 {
protected:
- int a; // { dg-message "" } protected
+ int a;
};
-class t2 : private t1 {
+class t2 : private t1 // { dg-message "" } protected
+{
public:
int b;
};
// { 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 {
int f () { return A::i; } // { dg-error "" } context