Bug 18385 – [REG 2.079] method cannot be overloaded with another extern(C) method

Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2018-02-06T16:08:00Z
Last change time
2018-07-01T21:51:41Z
Assigned to
No Owner
Creator
Jacob Carlborg
See also
https://issues.dlang.org/show_bug.cgi?id=15217

Comments

Comment #0 by doob — 2018-02-06T16:08:00Z
The following code compiles with latest DMD 2.078.1, but fails with DMD nightly v2.078.2-beta.1-651-gc55c9be60. extern (C): void foo(int) { } void foo(double) { } Note that global C function will not have a mangling, but methods of a struct or class declared as `extern (C)` will get mangled as a D method. This can be used as a callback function for a C function.
Comment #1 by slavo5150 — 2018-02-23T09:38:26Z
I tested this at the module level: https://run.dlang.io/is/6iuGF4 It fails with a "multiple definition" linker error for 2.071.2 ~ 2.074.1. It succeeds beginning with 2.075.1, but displays a linker warning "Warning: size of symbol `foo` changed" I don't think this should have ever compiled, and I'm tempted to say that this bug has finally been fixed. But I would be delighted to be proven wrong.
Comment #2 by bugzilla — 2018-02-23T10:29:03Z
Yes, it should never have compiled, and it cannot work, as two functions with the same mangled name cannot both exist in the executable.
Comment #3 by code — 2018-02-23T10:38:45Z
(In reply to Jacob Carlborg from comment #0) > Note that global C function will not have a mangling, but methods of a > struct or class declared as `extern (C)` will get mangled as a D method. > This can be used as a callback function for a C function. So you're bug report is about cat > bug.d << CODE struct S { extern(C) static void foo(int) {} extern(C) static void foo(double) {} } CODE dmd -c bug.d ---- Error: function bug.S.foo(double) cannot be overloaded with another extern(C) function at /home/dawg/Code/D/bug.d(3) ---- instead ? For top-level functions there is no way to just use C calling convention without the mangling, so the example from the OP will clearly lead to a multiple definition problem and undefined behavior dependening on various linker behaviors. Introduced here https://github.com/dlang/dmd/pull/7577. BTW, please use [Reg <upcoming version>] instead of a non-permanent [Reg nightly]. For nightlies it's the next major version, so 2.079.0 in your case.
Comment #4 by code — 2018-02-23T10:42:27Z
(In reply to Walter Bright from comment #2) > Yes, it should never have compiled, and it cannot work, as two functions > with the same mangled name cannot both exist in the executable. Not so fast, the report about methods being broken is still somewhat valid. In that case `extern(C)` only affects the calling convention but not the mangling, and has mentioned use-cases as callbacks. It's relatively easy to just use different names for that use-case, so we might decide to deprecate this overloading if that seems necessary.
Comment #5 by code — 2018-02-23T10:53:40Z
Comment #6 by doob — 2018-02-23T10:58:03Z
(In reply to Martin Nowak from comment #3) > So you're bug report is about > > cat > bug.d << CODE > struct S > { > extern(C) static void foo(int) {} > extern(C) static void foo(double) {} > } > CODE > dmd -c bug.d > ---- > Error: function bug.S.foo(double) cannot be overloaded with another > extern(C) function at /home/dawg/Code/D/bug.d(3) > ---- > > instead > ? Yes, I actually have a class. I just tried to reduce the test case as much as possible.
Comment #7 by Jesse.K.Phillips+D — 2018-02-23T18:32:03Z
So C clearly doesn't support function overloads, but D provides for better type checking and generally expects as much. I think it would be nice to allow D to specify function overloads if the C call is ultimately the same (parameter sizes and such). This way in D a function can be specified to accept pointer types of A, B, and C rather than needing to be a void* as it is defined in C. I think it is similar to marking a parameter const even though it has no meaning to C and isn't actually enforced. This also appears to be how DWT has utilized definitions. I've realized that my upgrade to dxml and DWT for an application has cause my application to not compile on any of the D compilers, so a solution here would be nice or for [18475] to be fixed on 2.078. 18475: https://issues.dlang.org/show_bug.cgi?id=18475
Comment #8 by doob — 2018-03-03T12:48:37Z
Comment #9 by greeenify — 2018-07-01T21:51:41Z
I revived the deprecation cycle at https://github.com/dlang/dmd/pull/8429. Please see the PR for the motivation and chime in if the summary there doesn't match your opinion / use cases.