On 10/11/2017 06:58 PM, Martin Sebor wrote: > On 10/11/2017 11:26 AM, Joseph Myers wrote: >> On Tue, 10 Oct 2017, Martin Sebor wrote: >> >>> The ideal solution for 1) would be a function pointer that can >>> never be used to call a function (i.e., the void* equivalent >>> for functions).[X] >> >> I don't think that's relevant. The normal idiom for this in modern C >> code, if not just using void *, is void (*) (void), and since the warning >> is supposed to be avoiding excessive false positives and detecting the >> cases that are likely to be used for ABI-incompatible calls, the warning >> should allow void (*) (void) there. > > I think we'll just have to agree to disagree. I'm not convinced > that using void(*)(void) for this is idiomatic or pervasive enough > to drive design decisions. Bernd mentioned just libgo and libffi > as the code bases that do, and both you and I have noted that any > pointer type works equally well for this purpose. The problem > with almost any type, including void(*) (void), is that they can > be misused to call the incompatible function. Since the sole > purpose of this new warning is to help find those misuses, > excluding void(*)(void) from the checking is directly at odds > with its goal.
Switching type-erased function pointers from "void(*)(void)" to "void(*)()" (in C) substantially increases the risk of code calling the type-erased pointer without casting it back by accident: extern void foo (int, int); typedef void (type_erased_func) (void); type_erased_func *func = (type_erased_func *) foo; int main () { func (1, 2); // error: too many arguments } vs: extern void foo (int, int); typedef void (type_erased_func) (); // note: void dropped type_erased_func *func = (type_erased_func *) foo; int main () { func (1, 2); // whoops, now silently compiles } I think it'd be good if this were weighed in as well. If 'void ()' is picked as the special type, then maybe the above could be at least addressed in the documentation, and/or diagnostics/notes. Thanks, Pedro Alves