Bug 23059 – importC: calls to D template functions don't convert some argument types
Status
RESOLVED
Resolution
WONTFIX
Severity
enhancement
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2022-04-25T00:35:47Z
Last change time
2022-04-30T03:55:48Z
Keywords
ImportC
Assigned to
No Owner
Creator
duser
Comments
Comment #0 by duser — 2022-04-25T00:35:47Z
// dmodule.di
void my_builtin_bswap16()(short x){}
void my_atomic_store_n(T)(T* ptr, T val, int memorder){}
// main.c
__import dmodule;
int main()
{
int x;
// Error: none of the overloads are callable using argument types `!()(int)`
// same with other bswap builtins when passed a bigger type than they expect
my_builtin_bswap16(x);
//my_builtin_bswap16((short)x); // works
int *p;
// Error: none of the overloads are callable using argument types `!()(int**, int, int)`
my_atomic_store_n(&p, 0, 0);
//my_atomic_store_n(&p, (int *)0, 0); // works
}
1. affects __builtin_bswapN() in druntime (when passed a larger type than they expect): the variable isn't converted to the smaller type in the call, so the template fails to match
2. affects my implementation of some gcc atomic builtins: when T is inferred as a pointer type by the first argument, passing "0" (or a number variable) as the second argument doesn't convert it to a pointer type
both are different from what you'd get when calling a non-templated C or D function, or the equivalent builtins in gcc
it would be nice if these worked more like in C so the templates didn't need to implement the conversions themselves
Comment #1 by bugzilla — 2022-04-30T03:55:48Z
1. As you note, unlike C, D doesn't do implicit integer narrowing conversions. Here, C is calling D templates, and isn't doing those conversions. Should they, is an interesting topic. I suggest that D templates are written to work with D style conversions. Adding a special case for C may wind up doing things like unexpectedly instantiate the wrong template. I am concerned this may be risky, and it may be difficult to set up templates that will work with both D and C.
Fortunately, the workarounds from the C side are simple - a cast. The accommodations for the D side are also simple - add more overloads that take the larger types, cast them, then forward to the function with the narrower types.
2. This is similar, allowing the C implicit conversion of integers to pointers. Frankly, this could be letting a cat loose in an aviary. I expect it would be pretty risky, and again the accommodations are simple, so it is not worth it to adjust the semantics.
We should be in good shape here without risking adding C's error prone implicit conversions on the D side.