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.