Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching an exception by value - gcc and clang disagree

Consider this short snippet:

struct B {
    B() = default;
    explicit B(B const& ) { }
};

struct D : B { };

int main() {
    try {
        throw D{};
    }
    catch(B ) {
    }
}

gcc accepts this code, clang considers it ill-formed with:

main.cpp:17:13: error: no matching constructor for initialization of 'B'
    catch(B ) {
            ^

Who's right?

like image 264
Barry Avatar asked Mar 23 '16 02:03

Barry


1 Answers

I think this is a gcc bug (and since nobody has downvoted this answer yet, I submitted it as 70375).

Both compilers correctly agree that D{} should be caught, as per [except.handle]/3, which only checks that B is a base class of D.

But the initialization of the handler is defined in [except.handle]/15 as:

The variable declared by the exception-declaration, of type cv T or cv T&, is initialized from the exception object, of type E, as follows:
— if T is a base class of E, the variable is copy-initialized (8.5) from the corresponding base class subobject of the exception object;

That implies that initialization works as:

D __temporary_object{};
B __handler = static_cast<B&>(__temporary_object);

which should be disallowed since B's copy constructor is marked explicit (and copy-initialization just doesn't cut it).

like image 97
Barry Avatar answered Sep 20 '22 12:09

Barry