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
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 mX;
template
constexpr beta(fn x): mX{static_cast>(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)
:29:31: error: 'constexpr H::beta::beta(H::fn) [with T = I; H::fn
= unsigned int (I::*)(unsigned int) const]' called in a constant expression
29 | constexpr H::beta x {&I::c};
| ^
:19:19: note: 'constexpr H::beta::beta(H::fn) [with T = I; H::fn
= unsigned int (I::*)(unsigned int) const]' is not usable as a 'constexpr'
function because:
19 | constexpr beta(fn x): mX{static_cast>(x)} {}
| ^~~~
:19:37: error: 'reinterpret_cast' is not a constant expression
19 | constexpr beta(fn x): mX{static_cast>(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)
:29:31: error: 'constexpr H::beta::beta(H::fn) [with T = I; H::fn
= unsigned int (I::*)(unsigned int) const; uint32_t = unsigned int]' called in
a constant expression
29 | constexpr H::beta x {&I::c};
| ^
:19:19: note: 'constexpr H::beta::beta(H::fn) [with T = I; H::fn
= unsigned int (I::*)(unsigned int) const; uint32_t = unsigned int]' is not
usable as a 'constexpr' function because:
19 | constexpr beta(fn x): mX{static_cast>(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 -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