diff --git a/mak/SRCS b/mak/SRCS index 955119dcd6..a8fdc8be3d 100644 --- a/mak/SRCS +++ b/mak/SRCS @@ -110,6 +110,7 @@ SRCS=\ src\core\stdcpp\new_.d \ src\core\stdcpp\string.d \ src\core\stdcpp\string_view.d \ + src\core\stdcpp\typeinfo.d \ src\core\stdcpp\type_traits.d \ src\core\stdcpp\utility.d \ src\core\stdcpp\vector.d \ diff --git a/src/core/stdcpp/exception.d b/src/core/stdcpp/exception.d index b855b20f0e..f920057cd0 100644 --- a/src/core/stdcpp/exception.d +++ b/src/core/stdcpp/exception.d @@ -105,16 +105,16 @@ else version (CppRuntime_Microsoft) /// this(const(char)* message = "unknown", int = 1) nothrow { msg = message; } /// - extern(D) ~this() nothrow {} + @weak ~this() nothrow {} /// - extern(D) const(char)* what() const nothrow { return msg != null ? msg : "unknown exception"; } + @weak const(char)* what() const nothrow { return msg != null ? msg : "unknown exception"; } // TODO: do we want this? exceptions are classes... ref types. // final ref exception opAssign(ref const(exception) e) nothrow { msg = e.msg; return this; } protected: - @weak void _Doraise() const {} + @weak void _Doraise() const { assert(0); } protected: const(char)* msg; @@ -130,4 +130,10 @@ class bad_exception : exception @nogc: /// this(const(char)* message = "bad exception") { super(message); } + + version (GenericBaseException) + { + /// + @weak override const(char)* what() const nothrow { return "bad exception"; } + } } diff --git a/src/core/stdcpp/typeinfo.d b/src/core/stdcpp/typeinfo.d index eee4331089..53b25c5e9a 100644 --- a/src/core/stdcpp/typeinfo.d +++ b/src/core/stdcpp/typeinfo.d @@ -18,6 +18,7 @@ version (CppRuntime_DigitalMars) import core.stdcpp.exception; extern (C++, "std"): + @nogc: class type_info { @@ -29,8 +30,8 @@ version (CppRuntime_DigitalMars) //bool operator==(const type_info rhs) const; //bool operator!=(const type_info rhs) const; - final bool before(const type_info rhs) const; - final const(char)* name() const; + final bool before(const type_info rhs) const nothrow; + final const(char)* name() const nothrow; protected: //type_info(); private: @@ -61,6 +62,7 @@ else version (CppRuntime_Microsoft) import core.stdcpp.exception; extern (C++, "std"): + @nogc: struct __type_info_node { @@ -72,12 +74,11 @@ else version (CppRuntime_Microsoft) class type_info { - //virtual ~this(); - void dtor() { } // reserve slot in vtbl[] + @weak ~this() nothrow {} //bool operator==(const type_info rhs) const; //bool operator!=(const type_info rhs) const; - final bool before(const type_info rhs) const; - final const(char)* name(__type_info_node* p = &__type_info_root_node) const; + final bool before(const type_info rhs) const nothrow; + final const(char)* name(__type_info_node* p = &__type_info_root_node) const nothrow; private: void* pdata; @@ -87,13 +88,13 @@ else version (CppRuntime_Microsoft) class bad_cast : exception { - this(const(char)* msg = "bad cast"); + this(const(char)* msg = "bad cast") @nogc nothrow { super(msg); } //virtual ~this(); } class bad_typeid : exception { - this(const(char)* msg = "bad typeid"); + this(const(char)* msg = "bad typeid") @nogc nothrow { super(msg); } //virtual ~this(); } } @@ -107,15 +108,17 @@ else version (CppRuntime_Gcc) } extern (C++, "std"): + @nogc: - class type_info + abstract class type_info { - void dtor1(); // consume destructor slot in vtbl[] - void dtor2(); // consume destructor slot in vtbl[] - @weak final const(char)* name()() const nothrow { + @weak ~this() {} + @weak final const(char)* name() const nothrow + { return _name[0] == '*' ? _name + 1 : _name; } - @weak final bool before()(const type_info _arg) const { + @weak final bool before(const type_info _arg) const nothrow + { import core.stdc.string : strcmp; return (_name[0] == '*' && _arg._name[0] == '*') ? _name < _arg._name @@ -127,22 +130,24 @@ else version (CppRuntime_Gcc) bool __do_catch(const type_info, void**, uint) const; bool __do_upcast(const __class_type_info*, void**) const; + protected: const(char)* _name; - this(const(char)*); + + this(const(char)* name) { _name = name; } } class bad_cast : exception { - this(); + this() nothrow {} //~this(); - @weak override const(char)* what() const; + @weak override const(char)* what() const nothrow { return "bad cast"; } } class bad_typeid : exception { - this(); + this() nothrow {} //~this(); - @weak override const(char)* what() const; + @weak override const(char)* what() const nothrow { return "bad typeid"; } } } else version (CppRuntime_Clang) @@ -150,6 +155,7 @@ else version (CppRuntime_Clang) import core.stdcpp.exception; extern (C++, "std"): + @nogc: abstract class type_info { @@ -167,21 +173,21 @@ else version (CppRuntime_Clang) protected: const(char)* __type_name; - extern(D) this(const(char)* __n) { __type_name = __n; } + this(const(char)* __n) { __type_name = __n; } } class bad_cast : exception { - this(); + this() nothrow {} //~this(); - @weak override const(char)* what() const; + @weak override const(char)* what() const nothrow { return "bad cast"; } } class bad_typeid : exception { - this(); + this() nothrow {} //~this(); - @weak override const(char)* what() const; + @weak override const(char)* what() const nothrow { return "bad typeid"; } } } else diff --git a/test/stdcpp/Makefile b/test/stdcpp/Makefile index 20629652d5..e8fd1ec964 100644 --- a/test/stdcpp/Makefile +++ b/test/stdcpp/Makefile @@ -13,6 +13,8 @@ ifeq (osx,$(OS)) # TESTS+=vector endif ifeq (linux,$(OS)) + TESTS11+=exception typeinfo + TESTS+=typeinfo # TESTS+=string # TESTS+=vector OLDABITESTS+=string diff --git a/test/stdcpp/src/exception.cpp b/test/stdcpp/src/exception.cpp new file mode 100644 index 0000000000..d0ca42c478 --- /dev/null +++ b/test/stdcpp/src/exception.cpp @@ -0,0 +1,21 @@ +#include + +void throw_exception() +{ + throw std::exception(); +} + +void throw_bad_exception() +{ + throw std::bad_exception(); +} + +class custom_exception : public std::exception +{ + const char* what() const noexcept { return "custom_exception"; } +}; + +void throw_custom_exception() +{ + throw custom_exception(); +} diff --git a/test/stdcpp/src/exception_test.d b/test/stdcpp/src/exception_test.d new file mode 100644 index 0000000000..bd44672fd8 --- /dev/null +++ b/test/stdcpp/src/exception_test.d @@ -0,0 +1,39 @@ +import core.stdc.string; +import core.stdcpp.exception; + +unittest +{ + try + { + throw_exception(); + } + catch (exception e) + { + const what = e.what(); + assert(!strcmp(what, "unknown") || // druntime override + !strcmp(what, "std::exception")); + } + try + { + throw_bad_exception(); + } + catch (exception e) + { + const what = e.what(); + assert(!strcmp(what, "bad exception") || // druntime override + !strcmp(what, "std::bad_exception")); + } + try + { + throw_custom_exception(); + } + catch (exception e) + { + assert(!strcmp(e.what(), "custom_exception")); + } +} + +extern(C++): +void throw_exception(); +void throw_bad_exception(); +void throw_custom_exception(); diff --git a/test/stdcpp/src/typeinfo.cpp b/test/stdcpp/src/typeinfo.cpp new file mode 100644 index 0000000000..68ab5eb6f7 --- /dev/null +++ b/test/stdcpp/src/typeinfo.cpp @@ -0,0 +1,40 @@ +#include + +void throw_bad_cast() +{ + throw std::bad_cast(); +} + +void throw_bad_typeid() +{ + throw std::bad_typeid(); +} + +const std::type_info& typeid_int() +{ + return typeid(int); +} + +const std::type_info& typeid_double() +{ + return typeid(double); +} + +class Toil { }; + +const std::type_info& typeid_toil() +{ + return typeid(Toil); +} + +const std::type_info& typeid_const_toil() +{ + return typeid(const Toil&); +} + +class Trouble { }; + +const std::type_info& typeid_trouble() +{ + return typeid(Trouble); +} diff --git a/test/stdcpp/src/typeinfo_test.d b/test/stdcpp/src/typeinfo_test.d new file mode 100644 index 0000000000..7933416a8a --- /dev/null +++ b/test/stdcpp/src/typeinfo_test.d @@ -0,0 +1,54 @@ +import core.stdc.string; +import core.stdcpp.typeinfo; + +unittest +{ + try + { + throw_bad_cast(); + } + catch (bad_cast e) + { + const what = e.what(); + assert(!strcmp(what, "bad cast") || // druntime override + !strcmp(what, "std::bad_cast")); + } + try + { + throw_bad_typeid(); + } + catch (bad_typeid e) + { + const what = e.what(); + assert(!strcmp(what, "bad typeid") || // druntime override + !strcmp(what, "std::bad_typeid")); + } + + const tid1 = typeid_int(); + const tid2 = typeid_double(); + assert(tid1 != tid2); + assert(!strcmp(tid1.name(), "i")); + assert(!strcmp(tid2.name(), "d")); + + const tid3 = typeid_toil(); + const tid4 = typeid_const_toil(); + assert(tid3 == tid4); + assert(!strcmp(tid3.name(), "4Toil")); + + const tid5 = typeid_trouble(); + assert(tid4 != tid5); + assert(!strcmp(tid5.name(), "7Trouble")); + + assert(tid2.before(tid1)); + assert(tid3.before(tid2)); + assert(tid4.before(tid5)); +} + +extern(C++): +void throw_bad_cast(); +void throw_bad_typeid(); +const(type_info) typeid_int(); +const(type_info) typeid_double(); +const(type_info) typeid_toil(); +const(type_info) typeid_const_toil(); +const(type_info) typeid_trouble();