Topic: return value dtor accessibility
Author: pavel@despammed.com ("Pavel Kuznetsov")
Date: Sun, 7 Aug 2005 01:26:56 GMT Raw View
Alberto,
thanks for your answer!
> MinGW looks the only compliant compiler here =:-|
I tried one of the fresh builds of VC++ 8, and it seems to reject all
of the three examples too.
> 12.2/1: "[...] Even when the creation of the temporary object is avoided
> (12.8), all the semantic restrictions must be respected as if the
> temporary object was created. [Example: even if the copy constructor
> is not called, all the semantic restrictions, such as accessibility
> (clause 11), shall be satisfied. ]"
>
> In other words, differences of RVO implementation should not affect the
> well-formedness of the code or lack thereof.
Yes, this is exactly the place of the standard I was thinking about, but
I am not sure whether we can rely on it, because as you are saying later,
it is not explicitly said, or to be more precise we were not able to find
corresponding wording, that the temporary returned is destroyed in the
context of the caller, and that dtor accessibility checks are done in
the context of the caller.
> BTW, I don't think that RVO is even involved in any of those examples,
> as it is an optimization that may affect the callee, but not to the
> caller.
Yes I thought the same, but the only thing which comes to my mind and
behaves that irregular and depends on the presence of user-defined copy
constructors, destructors etc. is RVO. But of course that was my wild
guess.
> It seems to me that everything you need is in 12.2/1 and 12.2/3:
I thought so until I noticed that 12.2/1 is talking about *returning* a
value, and not about *calling* a function, and I was not able to find
any particular place in the standard which would define where
accessibility of a destructor is checked for the value returned.
> 12.2/1: Temporaries of class type are created in various contexts:
> [...], returning an rvalue (6.6.3), [...]
> The only doubt I have with this argumentation is that 12.2/1 explicitly
> refers to 6.6.3 which is about the return statement, that is something
> which pertains to the callee context that returns the temporary but not
> to the caller context that receives the temporary, as in your examples.
Yes, that is exactly what confuses me.
> However I can't see how the compiler could avoid destroying the
> temporary in the caller context (sematically speaking, i.e.: regardless
> of optimizations).
Well that is why I think that all of my examples are ill-formed, but
I wanted to see an explicit provision in the standard, because common
sense is not enough when the major compilers disagree.
Anyway, thanks again for your interpretation.
I hope that somebody would be able to find some definitive place in the
standard which we could missed though...
Otherwise I think it would warrant a DR, wouldn't it?
--
Pavel
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Pavel Kuznetsov" <pavel@despammed.com>
Date: 5 Aug 2005 18:00:38 GMT Raw View
Should the examples below compile according to the
standard? And what is exact wording which leads to
the answer you propose?
(1)
struct A {
struct N {
private:
~N();
};
N n_;
};
A f();
int main()
{
f();
}
(2)
struct A {
private:
~A();
};
A f();
int main()
{
f();
}
(3)
struct A {
private:
A(A const&);
~A();
};
A f();
int main()
{
f();
}
My intuitive answer was 'no' for all three cases, because
at the point of the call of f() destructor of its return
value is either can't be implicitly defined,
or inaccessible.
But when I tried to compile these examples with four
different compilers, all of them gave different results:
(1) (2) (3)
CodeWarrior 9.5
for Mac OS X failed succeeded succeeded
MinGW GCC 3.4.2 failed failed failed
VC++7.1 succeeded failed failed
Comeau 4.3.3 for Windows succeeded succeeded failed
My understanding is that this difference can be explained
by subtle differences of RVO implementations. OTOH I always
thought that RVO should not influence dtor accessibility
checks in such cases...
I was not able to find exact wording (or combination of)
which would specify that destructor accessibility is
verified for return values of function calls at the point
of function call.
Is it my insufficient diligence or is it in fact
unspecified?
--
Pavel
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Alberto Barbati <AlbertoBarbati@libero.it>
Date: Fri, 5 Aug 2005 18:18:27 CST Raw View
Pavel Kuznetsov wrote:
> Should the examples below compile according to the
> standard? And what is exact wording which leads to
> the answer you propose?
>
> <snip example>
>
> My intuitive answer was 'no' for all three cases, because
> at the point of the call of f() destructor of its return
> value is either can't be implicitly defined,
> or inaccessible.
I agree with this interpretation.
> But when I tried to compile these examples with four
> different compilers, all of them gave different results:
>
> (1) (2) (3)
> CodeWarrior 9.5
> for Mac OS X failed succeeded succeeded
> MinGW GCC 3.4.2 failed failed failed
> VC++7.1 succeeded failed failed
> Comeau 4.3.3 for Windows succeeded succeeded failed
MinGW looks the only compliant compiler here =:-|
> My understanding is that this difference can be explained
> by subtle differences of RVO implementations. OTOH I always
> thought that RVO should not influence dtor accessibility
> checks in such cases...
12.2/1: "[...] Even when the creation of the temporary object is avoided
(12.8), all the semantic restrictions must be respected as if the
temporary object was created. [Example: even if the copy constructor
is not called, all the semantic restrictions, such as accessibility
(clause 11), shall be satisfied. ]"
In other words, differences of RVO implementation should not affect the
well-formedness of the code or lack thereof. BTW, I don't think that RVO
is even involved in any of those examples, as it is an optimization that
may affect the callee, but not to the caller.
> I was not able to find exact wording (or combination of)
> which would specify that destructor accessibility is
> verified for return values of function calls at the point
> of function call.
>
> Is it my insufficient diligence or is it in fact
> unspecified?
It seems to me that everything you need is in 12.2/1 and 12.2/3:
12.2/1: Temporaries of class type are created in various contexts:
[...], returning an rvalue (6.6.3), [...]
12.2/3: "[...] Similarly, the destructor shall be called for
a temporary with a non-trivial destructor (12.4). [...]"
Of course, class A has a non-trivial destructor in all three cases:
12.4/3: "[...] A destructor is trivial if it is an implicitly-declared
destructor and if:
all of the direct base classes of its class have trivial destructors and
for all of the non-static data members of its class that are of class
type (or array thereof), each such class has a trivial destructor."
In case (2) and (3) the destructor is not trivial because it is not
implicitly declared. Moreover, the destructor is inaccessible and so the
code is ill-formed by 11/4.
In case (1) there is a non-static data member that does not have a
trivial destructor (N::~N is not implicitly declared) and in that case
the code is ill-formed because of 12.4/5:
12.4/5: "An implicitly-declared destructor is implicitly defined when it
is used to destroy an object of its class type (3.7). A program is
ill-formed if the class for which a destructor is implicitly defined has:
a non-static data member of class type (or array thereof) with an
inaccessible destructor, or
a base class with an inaccessible destructor"
The only doubt I have with this argumentation is that 12.2/1 explicitly
refers to 6.6.3 which is about the return statement, that is something
which pertains to the callee context that returns the temporary but not
to the caller context that receives the temporary, as in your examples.
However I can't see how the compiler could avoid destroying the
temporary in the caller context (sematically speaking, i.e.: regardless
of optimizations).
HTH,
Alberto
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]