http://llvm.org/bugs/show_bug.cgi?id=12139
Douglas Gregor <[email protected]> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution| |INVALID --- Comment #2 from Douglas Gregor <[email protected]> 2012-03-09 18:16:09 CST --- Both GCC and Clang are correct here, even though they differ. Essentially, Clang is applying copy elision more aggressively than GCC, which is causing this code to do something different from what the author expected. Copy elision can be surprising that way, because it's explicitly stated that it can be applied even though it can change the result of programs. Specifically, what's happening in the first case is that A other(original.makeA(), PASSED_IN); is calling a copy constructor (since C++11 [class.copy]p2 considers that constructor a copy constructor). Then, C++11 [class.copy]p31 says that the compiler can omit the call to the copy constructor (3rd bullet): - when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move which means that the copy from the temporary "original.makeA()" can be elided, such that "other" directly gets the value of "original.makeA()". What does makeA() return? Well, we default-construct 'a' (so val has the value DEFAULT_CTOR) and then perform copy elision (the "named return value optimization", or NRVO) to end up directly returning that 'a' (without calling the copy constructor), so the resulting a have val == DEFAULT_CTOR. The second case is similar. However, makeStaticA() behaves differently because while static A a; gets the same val == DEFAULT_CTOR, the return statement cannot perform NRVO when returning a static local variable. Hence, the copy constructor gets called and we get back an object with val == DEFAULT_ARG. The third and fourth cases don't involve copy elision, since we're coming from an lvalue and not a temporary. Summing up, Clang is correctly performing copy elision, and the open source library in question will need to be fixed. I strongly suggest eliminating copy constructors that look like A(A const&, <parameters with default arguments>) and instead splitting them into A(const A&); // copy constructor A(const A&, <parameters>); // copy + tweak constructor so that differences in copy elision behavior between compilers don't continue to cause problems. -- Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are on the CC list for the bug. _______________________________________________ LLVMbugs mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/llvmbugs
