Bug 16527 – extern( C++ ) Win64 build - return struct by value is broken

Status
RESOLVED
Resolution
WORKSFORME
Severity
blocker
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Windows
Creation time
2016-09-23T14:48:18Z
Last change time
2018-05-14T14:13:32Z
Keywords
C++
Assigned to
No Owner
Creator
Ethan Watson
See also
https://issues.dlang.org/show_bug.cgi?id=13207

Comments

Comment #0 by gooberman — 2016-09-23T14:48:18Z
DMD 2.071.2, Windows, 64-bit output. The this pointer should be always stored in RCX, but the functions I'm using where structs are being returned by value switch the return address from RDX with RCX. While I'm actually using raw C++ functions through Binderoo, this is actually quite reproducible with D code that extern( C++ )'s its functions. Marking as blocker as there's a ridiculous number of functions we bind to that return structs by value that are just unusable. Code as follows: module thismodule; import std.stdio; import std.conv; align( 16 ) struct SomeCommonStruct { float valA = 0; float valB = 0; float valC = 0; float valD = 0; } struct SomeObject { void doAThing() { SomeWrapper aWrapper; SomeCommonStruct structThing = aWrapper.callme( &aWrapper ); writeln( to!string( structThing.valD ) ); } } extern( C++ ) struct SomeWrapper { SomeCommonStruct giveMeACommonStruct( SomeObject* pObject ) { return structeroo; } SomeCommonStruct structeroo = SomeCommonStruct( 1, 0, 3, 4 ); alias FnType = extern( C++ ) SomeCommonStruct function( SomeWrapper* ); __gshared extern( C++ ) SomeCommonStruct function( SomeWrapper* ) callme; } int main(string[] argv) { SomeWrapper.callme = cast( SomeWrapper.FnType )cast(void*)&SomeWrapper.giveMeACommonStruct; SomeObject someObject; someObject.doAThing(); return 0; } Expected: function SomeObject.doAThing writes the value "4" to stdout Actual: function SomeObject.doAThing writes rubbish to stdout
Comment #1 by kinke — 2016-09-24T08:47:01Z
We have a special case for this in LDC. MSVC passes `this` before `sret`, unlike most other ABIs.
Comment #2 by sprink.noreply — 2017-01-16T05:15:21Z
The problem is that there's no way to properly model a pointer to a member function to C++ from D. You can't use a delegate as it isn't supported with extern(C++). So there's no way for it to know that the parameter you are passing is actually a "this". Taking the address of a member function without an object is also broken (#3720).
Comment #3 by gooberman — 2018-05-14T14:13:32Z
Looks like this issue was fixed somewhere along the line. Example code works just fine on run.dlang.org, and the interop code I was working on for C# that was returning structs was also working just fine on DMD 2.078. No idea when exactly this would have been fixed, but it certainly Works For Me! now.