# DMD 2.081.0 Released

DMD 2.081.0 is now ready for download. Things that stand out in this release are a few deprecations, the implementation of a recently approved DIP (D Improvement Proposal), and quite a bit of work on C++ compatibility. Be sure to check the changelog for details.

## Improving C++ interoperability

D has had binary compatibility with C from the beginning not only because it made sense, but also because it was relatively easy to implement. C++ is a different beast. Its larger-than-C feature set and the differences between it and D introduce complexities that make implementing binary compatibility across all supported platforms a challenge to get right. Because of this, D’s extern(C++) feature has been considered a work in progress since its initial inception.

DMD 2.081.0 brings several improvements to the D <-> C++ story, mostly in the form of name mangling bug fixes and improvements. The mangling of constructors and destructors in extern(C++) now properly match the C++ side, as does that of most of D’s operator overloads (where they are semantically equivalent to C++).

Proper mangling of nullptr_t is implemented now as well. On the D side, use typeof(null):

alias nullptr_t = typeof(null);
extern(C++) void fun(nullptr_t);

The alias in the example is not required, but may help with usability and readability when interfacing with C++. As typing null everywhere is likely reflexive for most D programmers, nullptr_t may be easier to keep in mind than typeof(null) for those special C++ cases.

Most of the D operator overloads in an extern(C++) class will now correctly mangle. This means it’s now possible to bind to operator overloads in C++ classes using the standard D opBinary, opUnary, etc. The exceptions are opCmp, which has no compatible C++ implementation, and the C++ operator!, which has no compatible D implementation.

In addition to name mangling improvements, a nasty bug where extern(C++) destructors were being placed incorrectly in the C++ virtual table has been fixed, and extern(C++) constructors and destructors now semantically match C++. This means mixed-language class hierarchies are now possible and you can now pass extern(C++) classes to object.destroy when you’re done with them.

Indirectly related,  __traits(getLinkage, ...) has been updated to now tell you the ABI with which a struct, class, or interface has been declared, so you can now filter out your extern(C++) aggregates from those which are extern(D) and extern(Objective-C).

The following shows some of the new features in action. First, the C++ class:

#include <iostream>
class CClass {
private:
int _val;
public:
CClass(int v) : _val(v) {}
virtual ~CClass() { std::cout << "Goodbye #" << _val << std::endl; }
virtual int getVal() { return _val; }
CClass* operator+(CClass const * const rhs);
};

CClass* CClass::operator+(CClass const * const rhs) {
return new CClass(_val + rhs->_val);
}

And now the D side:

extern(C++) class CClass
{
private int _val;
this(int);
~this();
int getVal();
CClass opBinary(string op : "+")(const CClass foo);
}

class DClass : CClass
{
this(int v)
{
super(v);
}
~this() {}
override extern(C++) int getVal() { return super.getVal() + 10; }
}

void main()
{
import std.stdio : writeln;

DClass clazz1 = new DClass(5);
scope(exit) destroy(clazz1);
writeln("clazz1._val: ", clazz1.getVal());

DClass clazz2 = new DClass(6);
scope(exit) destroy(clazz2);
writeln("clazz2._val: ", clazz2.getVal());

CClass clazz3 = clazz1 + clazz2;
scope(exit) destroy(clazz3);
writeln("clazz3._val: ", clazz3.getVal);
}

Compile the C++ class to an object file with your C++ compiler, then pass the object file to DMD on the command line with the D source module and Bob’s your uncle (just make sure on Windows to pass -m64 or -m32mscoff to dmd if you compile the C++ file with the 64-bit or 32-bit Microsoft Build Tools, respectively).

This is still a work in progress and users diving into the deep end with C++ and D are bound to hit shallow spots more frequently than they would like, but this release marks a major leap forward in C++ interoperability.

## DIP 1009

Given the amount of time DIP 1009 spent crawling through the DIP review process, it was a big relief for all involved when it was finally approved. The DIP proposed a new syntax for contracts in D. For the uninitiated, the old syntax looked like this:

int fun(ref int a, int b)
in
{
// Preconditions
assert(a > 0);
assert(b >= 0, "b cannot be negative");
}
out(result) // (result) is optional if you don't need to test it
{
// Postconditions
assert(result > 0, "returned result must be positive");
assert(a != 0);
}
do
{
// The function body
a += b;
return b * 100;
}

Thanks to DIP 1009, starting in DMD 2.081.0 you can do all of that more concisely with the new expression-based contract syntax:

int fun(ref int a, int b)
in(a > 0)
in(b >= 0, "b cannot be negative")
out(result; result > 0, "returned result must be positive")
out(; a != 0)
{
a += b;
return b * 100;
}

Note that result is optional in both the old and new out contract syntaxes and can be given any name. Also note that the old syntax will continue to work.

## Deprecations

There’s not much information to add here beyond what’s already in the changelog, but these are cases that users should be aware of:

## The #dbugfix campaign

The inaugural #dbugfix round prior to the release of DMD 2.080 was a success, but Round 2 has been much, much quieter (few nominations, very little discussion, and no votes).

One of the two nominated bugs selected from Round 1 was issue #18068. It was fixed and merged into the new 2.081.0 release. The second bug selected was issue #15984, which has not yet been fixed.

In Round 2, the following bugs were nominated with one vote each:

I’ll hand this list off to our team of bug fixing volunteers and hope there’s something here they can tackle.

Round 3 of the #dbugfix campaign is on now. Please nominate the bugs you want to see fixed! Create a thread in the General Forum with #dbugfix and the issue number in the title, or send out a tweet containing #dbugfix and the issue number. I’ll tally them up at the end of the cycle (September 28).

And please, if you do use the #dbugfix in a tweet, remember that it’s intended for nominating bugs you want fixed and not for bringing attention to your pull requests!

## 5 thoughts on “DMD 2.081.0 Released”

1. Georg Wrede

#dbugfix should be changed to #dbugnominate

I think I don’t need to explain.

1. Michael Parker Post author

The end goal isn’t to nominate the bugs, but to get them fixed. Besides, #dbugfix is shorter and, IMO, catchier.

2. Kamyar Inanloo

Can I call OSRM (Open Source Routing Machine) now? It was too complicated the last time I tried!

1. Michael Parker Post author

I’m unfamiliar with that project, but looking at the code I see there may be some pain points. I suppose it depends on which parts of the API you need to use.