[Bug c++/105865] New: false positive expression static_cast pointer-to-member upcast in constexpr constructor

2022-06-06 Thread acox at reliablecontrols dot com via Gcc-bugs
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

[Bug c++/105865] false positive non-consant expression: static_cast pointer-to-member upcast in constexpr constructor

2022-06-07 Thread acox at reliablecontrols dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105865

--- Comment #1 from Alec  ---
It also works when trying to use a template helper outside of the constructor
See the example here https://godbolt.org/z/3raenhnjr

[Bug c++/105865] incorrect "not a consant expression": constexpr pointer-to-member upcast

2022-06-07 Thread acox at reliablecontrols dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105865

--- Comment #2 from Alec  ---
(In reply to Alec from comment #1)
> It also works when trying to use a template helper outside of the constructor
> See the example here https://godbolt.org/z/3raenhnjr

A regular static_cast placed where the template constexpr function is called in
that example will work, and obviously a define macro will work.

[Bug c++/117615] New: constexpr failure static_cast of Derived virtual Pointer to Member

2024-11-15 Thread acox at reliablecontrols dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117615

Bug ID: 117615
   Summary: constexpr failure static_cast of Derived virtual
Pointer to Member
   Product: gcc
   Version: 14.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: acox at reliablecontrols dot com
  Target Milestone: ---

Casting a virtual member function from the derived class fails to compile with
an error message complaining about a reinterpret_cast from a number to the
function signature. The number seems to be an offset, if you add a virtual
destructor to the Base class before the line doit is defined on the number
increases to 17.

https://godbolt.org/z/xPennWh15

: In function 'int main()':
:36:37:   in 'constexpr' expansion of 'help(&Derived::doit)'
:28:7: error: 'reinterpret_cast(1)' is not a
constant expression
   28 | : mFn(static_cast(fn))
  |   ^~
Compiler returned: 1

It compiles under the following changes
- if the member functions are made non-virtual
- if constexpr is removed from h
- if h is constructed with &Base::doit

Code from the godbolt link is included below as well.

```
#include 

#define BREAK_IT

struct Base {
#ifdef BREAK_IT
virtual
#endif
void doit(int v) const { std::cout << "doit base " << v; }
virtual ~Base() = default;

};

struct Derived : Base {
#ifdef BREAK_IT
virtual
#endif
void doit(int v) const { std::cout << "doit derived " << v; }
};

struct help
{
using fn_t = void (Base::*)(int) const;

fn_t mFn;

constexpr help(auto && fn)
: mFn(static_cast(fn))
{

}
};

int main()
{
constexpr help h (&Derived::doit);
Derived x;
(x.*h.mFn)(12);
}
```

[Bug c++/117615] constexpr failure static_cast of Derived virtual Pointer to Member

2024-11-15 Thread acox at reliablecontrols dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117615

--- Comment #1 from Alec  ---
It is worth noting that the same code compiles under clang-18 (haven't tested
other versions), although that doesn't mean they're doing the right thing.

[Bug c++/117615] [12/13/14/15 Regression] constexpr failure static_cast of Derived virtual Pointer to Member function since r6-4014-gdcdbc004d531b4

2024-12-05 Thread acox at reliablecontrols dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117615

--- Comment #12 from Alec  ---
Thank you guys for the speedy pickup, triage, and turnaround! Keep up the good
work!