https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105865
Bug ID: 105865 Summary: false positive expression static_cast pointer-to-member upcast in constexpr constructor Product: gcc Version: 12.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: acox at reliablecontrols dot com Target Milestone: --- G++ doesn't determine that an upcast on a pointer-to-member-function in a constexpr constructor is valid when used in a constexpr context. No options to g++ are needed, and there shouldn't be any preprocessing. struct H { template <class T> using fn = int (T::*)(int v) const; int a(int v) const { return v+40; } int b(int v) const { return v+20; } struct beta { fn<H> mX; template <class T> constexpr beta(fn<T> x): mX{static_cast<fn<H>>(x)} {} }; }; struct I : public H{ int c(int v) const { return v+40; } }; int main() { constexpr H::beta x {&I::c}; } On newer versions it will give this error message which is visually incorrect because it's a static_cast and not a reinterpret_cast. (this is from 12.1) <source>:29:31: error: 'constexpr H::beta::beta(H::fn<T>) [with T = I; H::fn<T> = unsigned int (I::*)(unsigned int) const]' called in a constant expression 29 | constexpr H::beta x {&I::c}; | ^ <source>:19:19: note: 'constexpr H::beta::beta(H::fn<T>) [with T = I; H::fn<T> = unsigned int (I::*)(unsigned int) const]' is not usable as a 'constexpr' function because: 19 | constexpr beta(fn<T> x): mX{static_cast<fn<H>>(x)} {} | ^~~~ <source>:19:37: error: 'reinterpret_cast' is not a constant expression 19 | constexpr beta(fn<T> x): mX{static_cast<fn<H>>(x)} {} | ^~~~~~~~~~~~~~~~~~~~~ On older versions it doesn't give any indication of what went wrong. Which is annoying with more constructor arguments and possible implicit converting constructors. (This is from 9.4) <source>:29:31: error: 'constexpr H::beta::beta(H::fn<T>) [with T = I; H::fn<T> = unsigned int (I::*)(unsigned int) const; uint32_t = unsigned int]' called in a constant expression 29 | constexpr H::beta x {&I::c}; | ^ <source>:19:19: note: 'constexpr H::beta::beta(H::fn<T>) [with T = I; H::fn<T> = unsigned int (I::*)(unsigned int) const; uint32_t = unsigned int]' is not usable as a 'constexpr' function because: 19 | constexpr beta(fn<T> x): mX{static_cast<fn<H>>(x)} {} | ^~~~ The issue goes away when you restructure the program to do the cast outside of the constructor. However, if you're intending to construct many objects at compile time this method can be cumbersome and overly verbose. This problem was previously described here: https://stackoverflow.com/q/46818864 I have reproduced it in a live environment here https://godbolt.org/z/vv1ocd77o to illustrate it does work with clang Version information (gcc -v) Target: x86_64-linux-gnu Configured with: ../gcc-12.1.0/configure --prefix=/opt/compiler-explorer/gcc-build/staging --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --disable-bootstrap --enable-multiarch --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --enable-clocale=gnu --enable-languages=c,c++,fortran,ada,go,d --enable-ld=yes --enable-gold=yes --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-linker-build-id --enable-lto --enable-plugins --enable-threads=posix --with-pkgversion=Compiler-Explorer-Build-gcc--binutils-2.38 --enable-libstdcxx-backtrace=yes Thread model: posix Supported LTO compression algorithms: zlib gcc version 12.1.0 (Compiler-Explorer-Build-gcc--binutils-2.38) COLLECT_GCC_OPTIONS='-fdiagnostics-color=always' '-g' '-o' '/app/output.s' '-masm=intel' '-S' '-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' '/app/' /opt/compiler-explorer/gcc-12.1.0/bin/../libexec/gcc/x86_64-linux-gnu/12.1.0/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -iprefix /opt/compiler-explorer/gcc-12.1.0/bin/../lib/gcc/x86_64-linux-gnu/12.1.0/ -D_GNU_SOURCE <source> -quiet -dumpdir /app/ -dumpbase output.cpp -dumpbase-ext .cpp -masm=intel -mtune=generic -march=x86-64 -g -version -fdiagnostics-color=always -o /app/output.s GNU C++17 (Compiler-Explorer-Build-gcc--binutils-2.38) version 12.1.0 (x86_64-linux-gnu) compiled by GNU C version 7.5.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version isl-0.24-GMP