D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 19563 - extern(C++) Incorrect ABI passing small struct
Summary: extern(C++) Incorrect ABI passing small struct
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86_64 Linux
: P1 blocker
Assignee: No Owner
URL:
Keywords: C++, industry, wrong-code
Depends on:
Blocks:
 
Reported: 2019-01-09 08:22 UTC by Manu
Modified: 2022-11-24 07:05 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Manu 2019-01-09 08:22:47 UTC
test.cpp
--------

struct Test
{
    Test() : ptr(nullptr) {}
    Test(const Test& x)
    {
        ptr = x.ptr + 10;
    }
    char* ptr;
};

int test(Test p);

int main()
{
    Test x;
    test(x);
    return 0;
}

test.d
------

extern(C++):

struct Test
{
    this(this)
    {
        ptr += 10;
    }
    char* ptr;
}

int test(Test p)
{
    assert(p.ptr == null);
    return 10;
}

--------------------------------------------

When I build and run this, passing `x` to test() by value crashes. The function receives garbage.

If you remove the copy constructors (pass this same struct as a POD), it works fine!

This was tested in Linux 64bit, against GCC-7.
If it makes any difference, I supplied `-std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0` to the C compiler.
Comment 1 Sprink 2019-02-08 01:54:57 UTC
Appears DMD doesn't take into consideration how to pass a struct based on anything other than the size of the struct. The Itantium ABI passes a pointer to the object if it has a copy constructor or destructor.

https://github.com/dlang/dmd/blob/v2.084.0/src/dmd/target.d#L688
https://github.com/dlang/dmd/blob/v2.084.0/src/dmd/backend/cod1.d#L4033

Somewhere in that mess of a backend. Good luck!

Either make sure your structs are more than 8 bytes as a workaround, or just use LDC they tend to have better C++ interactions.
Comment 2 Manu 2019-03-04 03:46:56 UTC
If anyone knows how to fix this; here's a head-start:

  https://github.com/dlang/dmd/pull/9411

That commits the unit-test which needs to work.
Comment 3 Manu 2019-03-04 03:49:01 UTC
This bug blocks the druntime `std::string` PR.
Comment 4 Dlang Bot 2019-03-09 20:47:36 UTC
@look-at-me created dlang/dmd pull request #9434 "Fix  Issue 19563 Fix extern(C++) Incorrect ABI passing small struct" mentioning this issue:

- Fix  Issue 19563 Fix extern(C++) Incorrect ABI passing small struct

https://github.com/dlang/dmd/pull/9434
Comment 5 Dlang Bot 2019-03-12 02:46:26 UTC
dlang/dmd pull request #9434 "Fix  Issue 19563 Fix extern(C++) Incorrect ABI passing small struct" was merged into master:

- bb2892490ee0df3f3fda486e8e549fdb4e58e37b by look-at-me:
  Fix Issue 19563 Fix extern(C++) Incorrect ABI passing small struct

https://github.com/dlang/dmd/pull/9434
Comment 6 Walter Bright 2022-11-24 07:03:59 UTC
This problem appears to have been introduced by https://github.com/dlang/dmd/pull/9434/
Comment 7 Walter Bright 2022-11-24 07:05:42 UTC
(In reply to Walter Bright from comment #6)
> This problem appears to have been introduced by
> https://github.com/dlang/dmd/pull/9434/

I mean it caused https://issues.dlang.org/show_bug.cgi?id=23195