public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor
@ 2012-10-29 16:00 ndkrempel at gmail dot com
  2012-10-29 16:09 ` [Bug c++/55120] " ndkrempel at gmail dot com
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: ndkrempel at gmail dot com @ 2012-10-29 16:00 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

             Bug #: 55120
           Summary: Inaccessible virtual base constructor does not prevent
                    generation of default constructor
    Classification: Unclassified
           Product: gcc
           Version: 4.7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: ndkrempel@gmail.com


The following code should fail to compile but does not:

struct V {};
struct B : private virtual V {};
struct D : B {};

int main() {
    D d;
}

According to N3376 section 12.1 paragraph 5, the defaulted default constructor
for D should be defined as deleted, as the default constructor for the virtual
base V is inaccessible from D.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor
  2012-10-29 16:00 [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor ndkrempel at gmail dot com
@ 2012-10-29 16:09 ` ndkrempel at gmail dot com
  2012-10-29 17:42 ` redi at gcc dot gnu.org
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: ndkrempel at gmail dot com @ 2012-10-29 16:09 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

--- Comment #1 from Nick Krempel <ndkrempel at gmail dot com> 2012-10-29 16:08:49 UTC ---
Not so clear this is a bug, as the default constructor for D could be generated
in the following form:

struct D : B {
  D() : B(), ::V() {}
}

Note the reference to V via the global scope, which is essential for it to
compile.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor
  2012-10-29 16:00 [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor ndkrempel at gmail dot com
  2012-10-29 16:09 ` [Bug c++/55120] " ndkrempel at gmail dot com
@ 2012-10-29 17:42 ` redi at gcc dot gnu.org
  2012-10-29 19:20 ` daniel.kruegler at googlemail dot com
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: redi at gcc dot gnu.org @ 2012-10-29 17:42 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jason at gcc dot gnu.org

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> 2012-10-29 17:42:20 UTC ---
This is http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#7 which was
closed as NAD saying "This is what was intended" but I'm not sure what "this"
is.

Jason?


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor
  2012-10-29 16:00 [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor ndkrempel at gmail dot com
  2012-10-29 16:09 ` [Bug c++/55120] " ndkrempel at gmail dot com
  2012-10-29 17:42 ` redi at gcc dot gnu.org
@ 2012-10-29 19:20 ` daniel.kruegler at googlemail dot com
  2012-10-29 22:42 ` ndkrempel at gmail dot com
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: daniel.kruegler at googlemail dot com @ 2012-10-29 19:20 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

--- Comment #3 from Daniel Krügler <daniel.kruegler at googlemail dot com> 2012-10-29 19:20:26 UTC ---
(In reply to comment #2)
> This is http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#7 which was
> closed as NAD saying "This is what was intended" but I'm not sure what "this"
> is.

Not being Jason, but this one made curious: I think the "this" refers to "In
short, it looks like a class with a virtual private base can't be derived
from.". I double-checked by contacting Mike who confirmed that "There's no
special treatment for access in indirect virtual base classes"


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor
  2012-10-29 16:00 [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor ndkrempel at gmail dot com
                   ` (2 preceding siblings ...)
  2012-10-29 19:20 ` daniel.kruegler at googlemail dot com
@ 2012-10-29 22:42 ` ndkrempel at gmail dot com
  2012-10-29 23:12 ` redi at gcc dot gnu.org
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: ndkrempel at gmail dot com @ 2012-10-29 22:42 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

--- Comment #4 from Nick Krempel <ndkrempel at gmail dot com> 2012-10-29 22:41:48 UTC ---
I think the standard is unclear on this. That defect report has been queried by
experts.

It comes down to something subtle about how the generated default constructor
attempts to refer to the virtual base - whether there is some kind of name
lookup of the virtual base itself going on, or whether it just 'knows' what the
right class is so that the only lookup is for the default constructor *within*
the virtual base class.

See Johannes Schaub's answer at http://stackoverflow.com/a/2371368/1395057 for
more along these lines, arguing that the current GCC behavior is in fact
correct. For what it's worth, I tend to agree with GCC's current behavior (and
it seems more useful too.)


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor
  2012-10-29 16:00 [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor ndkrempel at gmail dot com
                   ` (3 preceding siblings ...)
  2012-10-29 22:42 ` ndkrempel at gmail dot com
@ 2012-10-29 23:12 ` redi at gcc dot gnu.org
  2012-10-30  7:29 ` daniel.kruegler at googlemail dot com
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: redi at gcc dot gnu.org @ 2012-10-29 23:12 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> 2012-10-29 23:12:12 UTC ---
I think Johannes is right, the virtual base is default-initialized without
needing to look up its name in the scope of D, and the implicitly-defined
default constructor is public so accessible.

Curious that G++, Comeau and Clang all accept the example in CWG issue 7,
despite the rationale (and Mike) indicating it's intended that a virtual
private base can't be derived from.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor
  2012-10-29 16:00 [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor ndkrempel at gmail dot com
                   ` (4 preceding siblings ...)
  2012-10-29 23:12 ` redi at gcc dot gnu.org
@ 2012-10-30  7:29 ` daniel.kruegler at googlemail dot com
  2012-10-30 19:48 ` daniel.kruegler at googlemail dot com
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: daniel.kruegler at googlemail dot com @ 2012-10-30  7:29 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

--- Comment #6 from Daniel Krügler <daniel.kruegler at googlemail dot com> 2012-10-30 07:28:47 UTC ---
(In reply to comment #4)
> I think the standard is unclear on this. That defect report has been queried by
> experts.
Let me clarify that I have not even tried to interpret the standard, but I
wanted to get an understanding of what the issue's comment was supposed to
mean. These are two completely different things.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor
  2012-10-29 16:00 [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor ndkrempel at gmail dot com
                   ` (5 preceding siblings ...)
  2012-10-30  7:29 ` daniel.kruegler at googlemail dot com
@ 2012-10-30 19:48 ` daniel.kruegler at googlemail dot com
  2021-01-29 12:47 ` anthonysharp15 at gmail dot com
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: daniel.kruegler at googlemail dot com @ 2012-10-30 19:48 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

--- Comment #7 from Daniel Krügler <daniel.kruegler at googlemail dot com> 2012-10-30 19:48:21 UTC ---
(In reply to comment #5)
> Curious that G++, Comeau and Clang all accept the example in CWG issue 7,
> despite the rationale (and Mike) indicating it's intended that a virtual
> private base can't be derived from.

It has been explained to me that EDG's behaviour is a known bug.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor
  2012-10-29 16:00 [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor ndkrempel at gmail dot com
                   ` (6 preceding siblings ...)
  2012-10-30 19:48 ` daniel.kruegler at googlemail dot com
@ 2021-01-29 12:47 ` anthonysharp15 at gmail dot com
  2021-01-29 12:59 ` redi at gcc dot gnu.org
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: anthonysharp15 at gmail dot com @ 2021-01-29 12:47 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

Anthony Sharp <anthonysharp15 at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |anthonysharp15 at gmail dot com

--- Comment #8 from Anthony Sharp <anthonysharp15 at gmail dot com> ---
This issue was mentioned in pr17314 and Jason got verification from the C++
standards committee that it was expected behaviour that inaccessible virtual
constructors (or whatever one calls it - I'm not too clued up on the lingo)
should not work (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=17314).

As Jason says, a class with a virtual private base can't be derived from
(http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#7).

In fact, it seems that it is even the case that a public virtual base can't be
derived from (see pr17314 discussion - especially comment 17).

The latest version of the Visual Studio compiler gives the following warnings
when you attempt to derive from a private OR a public virtual base:

warning C4594: class 'cclass' can never be instantiated - indirect virtual base
class 'aclass' is inaccessible
message : 'aclass' is a private base class of 'bclass'
warning C4624: 'cclass': destructor was implicitly defined as deleted

GCC should generate a warning for this.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor
  2012-10-29 16:00 [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor ndkrempel at gmail dot com
                   ` (7 preceding siblings ...)
  2021-01-29 12:47 ` anthonysharp15 at gmail dot com
@ 2021-01-29 12:59 ` redi at gcc dot gnu.org
  2021-01-29 13:01 ` redi at gcc dot gnu.org
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: redi at gcc dot gnu.org @ 2021-01-29 12:59 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

--- Comment #9 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Nick Krempel from comment #0)
> The following code should fail to compile but does not:
> 
> struct V {};
> struct B : private virtual V {};
> struct D : B {};
> 
> int main() {
> 	D d;
> }
> 
> According to N3376 section 12.1 paragraph 5, the defaulted default
> constructor for D should be defined as deleted, as the default constructor
> for the virtual base V is inaccessible from D.

MSVC rejects this example, GCC, Clang and EDG accept it.

Oddly, Clang rejects it if ~V is user provided:

struct V { ~V() {} };
struct B : private virtual V {};
struct D : B {};
D d;

I have no idea why that makes a difference. GCC and EDG still accept that.

Clang doesn't care if V() is user provided, it will use it either way. It will
use ~V() if it's defined as deleted on its first declaration. It only rejects
it if ~V() is user provided.

I still don't know what the correct behaviour is.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor
  2012-10-29 16:00 [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor ndkrempel at gmail dot com
                   ` (8 preceding siblings ...)
  2021-01-29 12:59 ` redi at gcc dot gnu.org
@ 2021-01-29 13:01 ` redi at gcc dot gnu.org
  2021-01-29 22:55 ` richard-gccbugzilla at metafoo dot co.uk
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: redi at gcc dot gnu.org @ 2021-01-29 13:01 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
     Ever confirmed|0                           |1
                 CC|                            |richard-gccbugzilla@metafoo
                   |                            |.co.uk
           Keywords|                            |accepts-invalid
   Last reconfirmed|                            |2021-01-29

--- Comment #10 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Jonathan Wakely from comment #9)
> I still don't know what the correct behaviour is.

My comment crossed with Anthony's, but he confirms that the code is invalid, so
confirming as accepts-invalid.

It looks like Clang has a bug with the inaccessible constructor too, and
strangely inconsistent handling of the inaccessible destructor.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor
  2012-10-29 16:00 [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor ndkrempel at gmail dot com
                   ` (9 preceding siblings ...)
  2021-01-29 13:01 ` redi at gcc dot gnu.org
@ 2021-01-29 22:55 ` richard-gccbugzilla at metafoo dot co.uk
  2021-01-30 12:46 ` anthonysharp15 at gmail dot com
  2024-04-04 23:19 ` pinskia at gcc dot gnu.org
  12 siblings, 0 replies; 14+ messages in thread
From: richard-gccbugzilla at metafoo dot co.uk @ 2021-01-29 22:55 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

--- Comment #11 from Richard Smith <richard-gccbugzilla at metafoo dot co.uk> ---
(In reply to Jonathan Wakely from comment #10)
> It looks like Clang has a bug with the inaccessible constructor too, and
> strangely inconsistent handling of the inaccessible destructor.

Access checks are performed on names and on derived-to-base conversions.

On the constructor side, I think comment#4 is still relevant: it's not clear
that a defaulted constructor does anything that would require an access check.
I don't think it's clear that we perform a derived-to-base conversion, because
constructing a base class doesn't perform a normal member function call. (We're
not even *allowed* to perform a derived-to-virtual-base conversion until after
the base is constructed per the 'period of construction' rules.) And I don't
think it's reasonable to imagine that a defaulted constructor names its base
classes via injected-class-names or something like that -- that name could be
shadowed in the derived class with no effect on the validity of the defaulted
constructor. Likewise, I don't think we can imagine that the default
constructor for D names the default constructor of V as a member of D (which
would be inaccessible), because the default constructor of V is not inherited
into B and D by default, so we need to imagine it's named as a member of V, and
it's accessible as a member of V.

On the destructor side, I think [class.dtor]/7 is clear that only access to the
destructor is considered, not access to the base subobject, and [class.dtor]/14
says the call is performed as if with a qualified name, so the fact that the
destructor of the base is inaccessible as a member of the derived class is
irrelevant -- it's accessible as a member of the base class, so the access
check succeeds and the function is not deleted. However, I think the implicit
definition of the destructor is ill-formed under [class.dtor]/14, because a
derived-to-base conversion is presumably implied there.

I think Clang follows the above interpretation (it accepts the construction
side, does not treat the destructor as deleted, but rejects the implicit
definition of the destructor), except that it never triggers the implicit
definition of a trivial destructor, so it fails to diagnose the problem in the
definition of D::~D() for the example in comment#0. (But does diagnose if ~V is
non-trivial.)

I think we should ask to have the core issue reopened, because I don't think
the wording says anything sensible here. If we really want this case to be
ill-formed, we need clarification on whether that applies only to the
destruction side or also to construction, and presumably we should make the
destructor be deleted in this case, not merely be ill-formed when implicitly
defined.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor
  2012-10-29 16:00 [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor ndkrempel at gmail dot com
                   ` (10 preceding siblings ...)
  2021-01-29 22:55 ` richard-gccbugzilla at metafoo dot co.uk
@ 2021-01-30 12:46 ` anthonysharp15 at gmail dot com
  2024-04-04 23:19 ` pinskia at gcc dot gnu.org
  12 siblings, 0 replies; 14+ messages in thread
From: anthonysharp15 at gmail dot com @ 2021-01-30 12:46 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

--- Comment #12 from Anthony Sharp <anthonysharp15 at gmail dot com> ---
Okay, so it actually turns out public virtual bases CAN be derived from, since
the C++ spec literally gives an example of just that (e.g. see
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf at page 248
[I know it's the draft but I'm poor]).

As such, Visual Studio has no complaints about the following code:

class V {  };
class A : virtual public V {  };
class C : public A {  };

But it spits out warnings for this:

class V {  };
class A : virtual V {  };
class C : public A {  };

The problem is this issue requires such in-depth knowledge of the standard that
it's difficult to form an actual opinion on it. I will do some more research
and then maybe I'll be able to comment more. Overall though it seems the issue
is whether private inheritance affects the accessibility of the destructor
and/or constructor of a virtually-inherited baseclass to other deriving
classes. I could be wrong about that though.

What I will say though is that even without having to dive into the technical
details, the fact that one would not be able to derive from a private virtual
base makes no sense, intuitively speaking. A private base can be derived from.
A virtual base can be derived from. I don't see why it should make any
practical difference that the base might be both virtual and private.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor
  2012-10-29 16:00 [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor ndkrempel at gmail dot com
                   ` (11 preceding siblings ...)
  2021-01-30 12:46 ` anthonysharp15 at gmail dot com
@ 2024-04-04 23:19 ` pinskia at gcc dot gnu.org
  12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-04-04 23:19 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |zhonghao at pku dot org.cn

--- Comment #13 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
*** Bug 86238 has been marked as a duplicate of this bug. ***

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2024-04-04 23:19 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-29 16:00 [Bug c++/55120] New: Inaccessible virtual base constructor does not prevent generation of default constructor ndkrempel at gmail dot com
2012-10-29 16:09 ` [Bug c++/55120] " ndkrempel at gmail dot com
2012-10-29 17:42 ` redi at gcc dot gnu.org
2012-10-29 19:20 ` daniel.kruegler at googlemail dot com
2012-10-29 22:42 ` ndkrempel at gmail dot com
2012-10-29 23:12 ` redi at gcc dot gnu.org
2012-10-30  7:29 ` daniel.kruegler at googlemail dot com
2012-10-30 19:48 ` daniel.kruegler at googlemail dot com
2021-01-29 12:47 ` anthonysharp15 at gmail dot com
2021-01-29 12:59 ` redi at gcc dot gnu.org
2021-01-29 13:01 ` redi at gcc dot gnu.org
2021-01-29 22:55 ` richard-gccbugzilla at metafoo dot co.uk
2021-01-30 12:46 ` anthonysharp15 at gmail dot com
2024-04-04 23:19 ` pinskia at gcc dot gnu.org

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).