https://godbolt.org/z/jhcP8WPn8 Code to reproduce ================= struct S {}; constexpr int f(S s) { constexpr S _ = s; return 0; } S s; constexpr int _ = f(s); Issue description ================= This code compiles, but should produce errors for both constexpr initializations. According to [expr.const] p5.9, the initializers of _ cannot be constant expression because they contain lvalue-to-rvalue conversion of s, whose lifetime did not begin within the evaluation of the constant expression, and which is not usable in constant expressions. It shouldn't matter whether S is an empty class or has members; the lvalue-to-rvalue conversion in itself disqualifies expressions from being constant expressions.
Hmm, clang also accepts this ...
Corresponding LLVM bug: https://github.com/llvm/llvm-project/issues/83712
https://gcc.gnu.org/pipermail/gcc-patches/2020-February/539673.html hmm reading https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91953#c3 implies there is no lvalue-to-rvalue conversion happening ...
I don't see how lvalue-to-rvalue conversion would be bypassed here. https://eel.is/c++draft/conv.lval#:conversion,lvalue-to-rvalue has no special provision for empty classes. https://eel.is/c++draft/dcl.init.general#16.9 would necessitate lvalue-to-rvalue conversion because the initializer has to be converted to a prvalue. I couldn't find any special rule for empty classes.
Looks like the existing comments were right. Lvalue-to-rvalue conversion very rarely takes place for class types, and if it does, that may be a wording bug. Instead of lvalue-to-rvalue conversion, this case calls the implicitly-defined copy constructor, which can be used in constant expressions.