C++ Logo

std-discussion

Advanced search

Re: Is the standard clear enough about throwing exceptions from functions that return prvalues?

From: Brian Bi <bbi5291_at_[hidden]>
Date: Fri, 20 Sep 2019 13:13:31 -0500
On Fri, Sep 20, 2019 at 12:19 PM Andrew Schepler <aschepler_at_[hidden]>
wrote:

> By my reading, foo should catch the exception, so gcc and clang are
> correct. The key quote is [stmt.return]/2
> <https://timsong-cpp.github.io/cppwp/stmt.return#2>: When the returned
> initializer is not an expression with type void,
>
> the return statement initializes the glvalue result or prvalue result
> object of the (explicit or implicit) function call by copy-initialization
> from the operand.
>
>
I guess that wording is clear enough - it implies that no matter where the
result object happens to be defined, the return statement that creates the
prvalue also creates the prvalue's result object. Thanks for tracking it
down.


>
> So even though the prvalue result object is s in main, the initialization
> and the exception throwing happen in foo.
>
> I suppose this means we should think of prvalue temporary materialization
> as only a piece of semantic analysis of a class type expression in its
> context, and not something that gets "executed" by the virtual machine.
>
> -- Andrew Schepler
>
>
>
> On Fri, Sep 20, 2019 at 12:36 PM Brian Bi via Std-Discussion <
> std-discussion_at_[hidden]> wrote:
>
>> In the following program, no prvalue materialization conversion should
>> occur. Instead, s should just be value-initialized:
>>
>> #include <iostream>
>>
>> struct S {
>> S() { throw 42; }
>> S(S&&) { std::cout << "I am nontrivial" << std::endl; }
>> };
>>
>> S foo() {
>> try {
>> return {};
>> } catch (int) {
>> std::cout << "caught by foo\n";
>> throw;
>> }
>> }
>>
>> int main() {
>> try {
>> S s = foo();
>> } catch (int) {
>> std::cout << "caught by main\n";
>> }
>> }
>>
>> Therefore, I would expect that the constructor of S should be called in
>> the context of the definition of s, and foo should not have the
>> opportunity to catch the exception. Put another way, conceptually, the last
>> thing foo() does before it returns is to create a prvalue that says to
>> value-initialize the S object (whenever that might finally be required);
>> it doesn't get to actually call the constructor.
>>
>> Yet GCC and Clang both give foo the opportunity to catch the exception,
>> as if the constructor call were being done in the context of foo.
>> http://coliru.stacked-crooked.com/a/ae2943b361ab51a9
>>
>> Is the standard clear enough that the behaviour of GCC and Clang in this
>> case is actually the intended behaviour? I think that it is not clear.
>>
>> --
>> *Brian Bi*
>> --
>> Std-Discussion mailing list
>> Std-Discussion_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>
>

-- 
*Brian Bi*

Received on 2019-09-20 13:15:52