IR parsing problem for "no prototype" C function after opaque pointer transition

On most targets other than x86-64, clang emits a call to a no prototype C function as a CallInst with a llvm::FunctionType that is not variadic, while the function definition is variadic.

Prior to opaque pointers, the call involved a bitcast of the Function. After the opaque pointer transition the bitcast no longer exists.

This leads to textual IR that can’t be parsed back in because the FunctionType from the call is used to forward declare the Function and it doesn’t match the real declaration. With the bitcast both types could be expressed.

You can see the different IR between x86-64 and RISC-V here Compiler Explorer

If we paste the IR from RISC-V back in we get an error Compiler Explorer
error: invalid forward reference to function 'bar' with wrong type: expected 'void (...)*' but was 'void ()*'

This was mentioned in ⚙ D123300 [Clang] Enable opaque pointers by default.

Currently during the opaque pointer transition we don’t know whether to parse in typed pointer or opaque pointer mode yet. If -opaque-pointers=[0|1] is specified then we’ll use that value. Otherwise we have a hacky heuristic for parsing IR which is basically look for either ptr or *. Lacking either one, we fall back on the default, which is currently off for everything except clang.

The IR you posted does successfully parse with -opaque-pointers, which is the proper solution for now. But while we’re in the middle of the opaque pointer transition where some tools default to opaque pointers and some to typed pointers there’ll be some unfortunate circumstances like the IR you posted where the hacky heuristic doesn’t work.

Thank you. I didn’t even think about trying that. I got distracted trying to figure out why x86 and RISC-V were different.