Any libunwind experts n da house?
IgorStepanov via Digitalmars-d
digitalmars-d at puremagic.com
Sun Sep 28 14:22:25 PDT 2014
On Saturday, 27 September 2014 at 23:31:17 UTC, Andrei
Alexandrescu wrote:
> On 9/27/14, 1:31 PM, IgorStepanov wrote:
>> No, that for throwing from C++ into D: for catch an exception,
>> we should
>> pass type_info object to special C++ runtime function. C++
>> runtime
>> determines, can throwed object type can be casted to asked
>> type, and if
>> yes - allow catch it and do catcher code. If you will see the
>> my
>> example, you will see that I do this manually: get throwed
>> type_info and
>> compare its mangle with requested mangle. If we will make it as
>> possible, it will be work better, faster and reliable. As
>> bonus:
>> possibility to implement dynamic_cast over C++ classes.
>
> If that's what's needed, definitely please do explore it! But I
> defer expertise to Walter. -- Andrei
Ok. Anyway, I can't work on this to the full extent, because I
have a three D works (six pull requests), which are waiting for
action from the D collaborators (UDA for modules PR reviewed and
is waiting for approval, multiple alias this and new AA
implementation are waiting for review).
However, I've seen this direction and I want to report a few
points:
1. C++ type_info/TypeHandle for classes is located on -1 index of
vtbl;
2. type_info layout aren't standartized (as expected) and differs
in G++, VS and (probably) DMC and SunC.
3. type_info in C++ uses in many different cases, like
dynamic_cast and excetion handling.
4. D doensn't generate type_info and it can cause danger
situation. e.g.
************************************
//C++ code
class CppBase
{
public:
virtual void test() = 0;
};
class CppDerived : public CppBase
{
public:
void test();
};
void CppDerived::test()
{
std::cout << "CppDerived::test()" << std::endl;
}
void doTest(CppBase *obj)
{
obj->test();
CppDerived *dobj = dynamic_cast<CppDerived *>(obj);
//Attention!
if (dobj)
{
std::cout << "casted" << std::endl;
}
else
{
std::cout << "fail" << std::endl;
}
}
//D code
extern(C++) interface CppBase
{
void test();
}
class DDerived : CppBase
{
extern(C++) override void test()
{
writeln("DDerived.test()");
}
}
extern(C++) void doTest(CppBase);
void main()
{
writeln("start test");
doTest(new DDerived()); //BOOM! segfault while processing
dynamic_cast, because DDerived type_info is wrong.
writeln("finish test");
}
************************************
//Now my suggestions:
1. We can implement type_info generation as library template like
GenTypeInfo(T). It will return valid type_info object for
supproted platforms and null for platforms, which isn't supported
yet.
2. Compiler will use this template to get type_info and push it
into vtbl (at -1 position)
3. In situation, when compile need to use type_info (may be
try-catch with C++ exceptions or dynamic_cast, it will be raise
error if type_info isn't implemented)
This approach allows to move complex, platform-depended code from
compiler to library. Also it allows to don't implement some
platforms without user restrictions.
In conclusion: this is a g++ type_info definitions:
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/cxxabi.h#L535
This has a flag "__diamond_shaped_mask" in __vmi_class_type_info,
and "__virtual_mask" in __base_class_type_info.
D allows multiply inheritance for interfaces. In mapping to C++:
Is this inheritance virtual? Should we set __diamond_shaped_mask
is A: B, C; B : D; C : D (B, C, D is interfaces)?
More information about the Digitalmars-d
mailing list