Open
Description
#include <iostream>
struct Elem {
unsigned short data;
constexpr Elem(unsigned int a) noexcept : data(static_cast<unsigned short>(a)){};
Elem(const Elem& elem) : data(elem.data) { std::cout<<"call copy constructor\n"; }; // error with clang -std=c++14, ok with gcc and msvc
// constexpr Elem(const Elem& elem) : data(elem.data) {}; // ok
};
constexpr Elem foo() noexcept {
return Elem{0x0400};
}
int main() {
Elem e1 = foo();
std::cout<<e1.data<<std::endl;
}
<source>:10:17: error: constexpr function never produces a constant expression [-Winvalid-constexpr]
10 | constexpr Elem foo() noexcept {
| ^~~
<source>:11:12: note: non-constexpr constructor 'Elem' cannot be used in a constant expression
11 | return Elem{0x0400};
| ^
<source>:6:5: note: declared here
6 | Elem(const Elem& elem) : data(elem.data) { std::cout<<"call copy constructor\n"; }; // error with clang -std=c++14, ok with gcc and msvc
| ^
1 error generated.
With -std=c++14 flag, Clang performs the copy elision for the return statement in foo(), but still reports error about the copy constructor. I know copy elision is not guaranteed with pre-C++17, but since clang does perform it, there should not be an error.
When C++ standard is not specified, Clang-15 reports an error while higher versions do not.
GCC and MSVC have no problem with this code sample.