In C, we allow pointer conversions like:
void foo(int *a); long b; void runFoo() { foo(&b); }
...But not when overloading:
int bar(char *a) __attribute__((overloadable)); int bar(struct{}) __attribute__((overloadable)); unsigned char d; void runBar() { bar(&d); } // error: no matching function for call to 'bar'
This patch makes it so bar(&d) isn't an error.
A few notes:
- We'll still emit a warning about the conversion, assuming the user hasn't opted out of said warnings.
- Every such conversion is ranked as the worst possible thing. So, if there's any ambiguity at all (e.g. if bar had a void(signed char*) overload, as well), we'll still emit an error.
- We consider conversions that drop qualifiers to be equally as bad as converting between incompatible pointer types. I'm happy to make conversions that only drop qualifiers preferred over incompatible pointer types, if that would be better.
Yuck, this violates our invariants: First should only ever be some kind of lvalue conversion (it should in this case be an ICK_Array_To_Pointer or ICK_Function_To_Pointer if the argument was an array or function, respectively, and otherwise ICK_Identity). Third should only ever be ICK_Identity or ICK_Qualification. It seems fine to always set Third to ICK_Identity and model the qualification change as part of the second "standard" conversion; this should still compare worse than any other sequence by the rank test.
Now I've noticed this, I'd like to see it fixed, but since this is pre-existing I don't mind whether we fix this as part of this change or separately.