https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117925

            Bug ID: 117925
           Summary: ice unexpected expression '(FnPtr)(fnPtr)' of kind
                    cast_expr
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rogerio.souza at gmail dot com
  Target Milestone: ---

GCC 14 returns a compiler internal error  for the code below
(https://godbolt.org/z/b8EenvKj8):

************

using FnPtr = int(*)();

template <int T>
void fnICE(void* fnPtr)
{
    ((FnPtr)fnPtr)();
}

************

The error message is:

************

<source>: In function 'void fnICE(void*)':
<source>:6:6: internal compiler error: unexpected expression '(FnPtr)(fnPtr)'
of kind cast_expr
    6 |     ((FnPtr)fnPtr)();
      |     ~^~~~~~~~~~~~~
0x2031cbc internal_error(char const*, ...)
        ???:0
0x7f6550 cp_get_fndecl_from_callee(tree_node*, bool)
        ???:0
0x7f6be1 convert_to_void(tree_node*, impl_conv_void, int)
        ???:0
0x95bca1 finish_expr_stmt(tree_node*)
        ???:0
0x90ee14 c_parse_file()
        ???:0
0xa0d1b9 c_common_parse_file()
        ???:0
Please submit a full bug report, with preprocessed source (by using
-freport-bug).
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
Compiler returned: 1

************

It is interesting that the code is "(ucis_InternalSetValueRangePtr)fnPtr)", but
the GCC reports it as "(ucis_InternalSetValueRangePtr)(fnPtr)", with one
parenthese before "fnPtr".

>From man 3 dlopen:

           /* According to the ISO C standard, casting between function
              pointers and 'void *', as done above, produces undefined results.
              POSIX.1-2003 and POSIX.1-2008 accepted this state of affairs and
              proposed the following workaround:

                  *(void **) (&cosine) = dlsym(handle, "cos");

              This (clumsy) cast conforms with the ISO C standard and will
              avoid any compiler warnings.

              The 2013 Technical Corrigendum to POSIX.1-2008 (a.k.a.
              POSIX.1-2013) improved matters by requiring that conforming
              implementations support casting 'void *' to a function pointer.
              Nevertheless, some compilers (e.g., gcc with the '-pedantic'
              option) may complain about the cast used in this program. */

Based on this we were able to provide the work around
(https://godbolt.org/z/jaKhPWPvT):

***************

using FnPtr = int(*)();

template <int T>
void fnICE(void* fnPtr)
{
    FnPtr fn;
    *(void**) &fn = fnPtr;
    fn();
}

***************

Although we have the workaround GCC should not ICE, so I consider it a real bug
that should be fixed.

Reply via email to