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.

Reply via email to