Please see this example
#include <iostream>
struct A{
A(){
std::cout<<"A constructed\n";
}
~A(){
std::cout<<"A destroyed\n";
}
};
struct B{
B(int){
std::cout<<"B constructed\n";
}
~B(){
std::cout<<"B destroyed\n";
}
};
struct C{
C(){
std::cout<<"C constructed\n";
}
~C(){
std::cout<<"C destroyed\n";
}
bool operator==(B const&){
return true;
}
};
struct D{
D(bool){
std::cout<<"D constructed\n";
}
};
bool fun(){
A a;
C c;
return c==0;
}
int main(){
D d = fun();
}
The outputs of the above example are identity in both GCC and Clang, they are that
A constructed
C constructed
B constructed
B destroyed
C destroyed
A destroyed
D constructed
That means the copy-initialization of the result of the call is sequenced after all the destruction of the local or temporary variable of that function. It contradicts with the following rule, which is
[stmt.return#3]
The copy-initialization of the result of the call is sequenced before the destruction of temporaries at the end of the full-expression established by the operand of the return statement, which, in turn, is sequenced before the destruction of local variables ([stmt.jump]) of the block enclosing the return statement.
According to the rule, the output should be that
A constructed
C constructed
B constructed
D constructed
B destroyed
C destroyed
A destroyed
Is it a bug of GCC and Clang?