From 067064170b04a26e6370ef0ce009041cac71e798 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 28 Jul 2014 14:50:49 -0700 Subject: [PATCH 1/3] update test_files --- tests/test_core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_core.py b/tests/test_core.py index 7c9b18bfce2a3..389444520e24c 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -4095,7 +4095,7 @@ def process(filename): for mode in [[], ['-s', 'MEMFS_APPEND_TO_TYPED_ARRAYS=1']]: self.emcc_args = orig_args + mode try_delete(mem_file) - self.do_run(src, ('size: 7\ndata: 100,-56,50,25,10,77,123\nloop: 100 -56 50 25 10 77 123 \ninput:hi there!\ntexto\n$\n5 : 10,30,20,11,88\nother=some data.\nseeked=me da.\nseeked=ata.\nseeked=ta.\nfscanfed: 10 - hello\nok.\ntexte\n', 'size: 7\ndata: 100,-56,50,25,10,77,123\nloop: 100 -56 50 25 10 77 123 \ninput:hi there!\ntexto\ntexte\n$\n5 : 10,30,20,11,88\nother=some data.\nseeked=me da.\nseeked=ata.\nseeked=ta.\nfscanfed: 10 - hello\nok.\n'), + self.do_run(src, ('size: 7\ndata: 100,-56,50,25,10,77,123\nloop: 100 -56 50 25 10 77 123 \ninput:hi there!\ntexto\n$\n5 : 10,30,20,11,88\nother=some data.\nseeked=me da.\nseeked=ata.\nseeked=ta.\nfscanfed: 10 - hello\nok.\n \ntexte\n', 'size: 7\ndata: 100,-56,50,25,10,77,123\nloop: 100 -56 50 25 10 77 123 \ninput:hi there!\ntexto\ntexte\n$\n5 : 10,30,20,11,88\nother=some data.\nseeked=me da.\nseeked=ata.\nseeked=ta.\nfscanfed: 10 - hello\nok.\n'), post_build=post, extra_emscripten_args=['-H', 'libc/fcntl.h']) if self.emcc_args and '-O2' in self.emcc_args: assert os.path.exists(mem_file) @@ -4131,7 +4131,7 @@ def process(filename): ''' def clean(out, err): return '\n'.join(filter(lambda line: 'warning' not in line, (out + err).split('\n'))) - self.do_run(src, ('got: 35\ngot: 45\ngot: 25\ngot: 15\nisatty? 0,0,1\n', 'isatty? 0,0,1\ngot: 35\ngot: 45\ngot: 25\ngot: 15\n'), post_build=post, output_nicerizer=clean) + self.do_run(src, ('got: 35\ngot: 45\ngot: 25\ngot: 15\n \nisatty? 0,0,1\n', 'got: 35\ngot: 45\ngot: 25\ngot: 15\nisatty? 0,0,1\n', 'isatty? 0,0,1\ngot: 35\ngot: 45\ngot: 25\ngot: 15\n'), post_build=post, output_nicerizer=clean) def test_mount(self): src = open(path_from_root('tests', 'fs', 'test_mount.c'), 'r').read() From 9f5e322341ec5c4b265a42c282828c8de6022989 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 28 Jul 2014 14:55:51 -0700 Subject: [PATCH 2/3] update test_memcpy_memcmp --- tests/test_core.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_core.py b/tests/test_core.py index 389444520e24c..a955e3b0563b9 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -2723,6 +2723,7 @@ def test_memcpy_memcmp(self): src, output = (test_path + s for s in ('.in', '.out')) def check(result, err): + result = result.replace('\n \n', '\n') # remove extra node output return hashlib.sha1(result).hexdigest() self.do_run_from_file(src, output, output_nicerizer = check) From 9aa8ab3fdd5ec0913e41eafef3b920d32a532117 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 28 Jul 2014 15:36:14 -0700 Subject: [PATCH 3/3] support exceptions with virtual inheritance, by letting libcxxabi adjust the pointer as an out param; fixes #2531; 1.21.9 --- emscripten-version.txt | 2 +- src/library.js | 21 +++++++------- system/lib/libcxxabi/src/private_typeinfo.cpp | 8 ++++-- .../test_exceptions_virtual_inheritance.cpp | 28 +++++++++++++++++++ .../test_exceptions_virtual_inheritance.txt | 2 ++ tests/test_core.py | 11 ++++++++ 6 files changed, 57 insertions(+), 15 deletions(-) create mode 100644 tests/core/test_exceptions_virtual_inheritance.cpp create mode 100644 tests/core/test_exceptions_virtual_inheritance.txt diff --git a/emscripten-version.txt b/emscripten-version.txt index db98d22c01c7e..6c13ae0d09f3e 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.21.8 +1.21.9 diff --git a/src/library.js b/src/library.js index 4828363d5cad9..6c84e590a38fe 100644 --- a/src/library.js +++ b/src/library.js @@ -4010,28 +4010,27 @@ LibraryManager.library = { if (throwntype == -1) throwntype = {{{ makeGetValue('header', 0, 'void*') }}}; var typeArray = Array.prototype.slice.call(arguments, 2); - // If throwntype is a pointer, this means a pointer has been - // thrown. When a pointer is thrown, actually what's thrown - // is a pointer to the pointer. We'll dereference it. - var thrownPtr = thrown; - if (throwntype != 0 && Module['___cxa_is_pointer_type'](throwntype)) { - var throwntypeInfoAddr= {{{ makeGetValue('throwntype', '0', '*') }}} - {{{ Runtime.QUANTUM_SIZE*2 }}}; - var throwntypeInfo= {{{ makeGetValue('throwntypeInfoAddr', '0', '*') }}}; - if (throwntypeInfo == 0) - thrown = {{{ makeGetValue('thrown', '0', '*') }}}; - } + assert(throwntype); + + var pointer = Module['___cxa_is_pointer_type'](throwntype); + // can_catch receives a **, add indirection + if (!___cxa_find_matching_catch.buffer) ___cxa_find_matching_catch.buffer = _malloc(4); + {{{ makeSetValue('___cxa_find_matching_catch.buffer', '0', 'thrown', '*') }}}; + thrown = ___cxa_find_matching_catch.buffer; // The different catch blocks are denoted by different types. // Due to inheritance, those types may not precisely match the // type of the thrown object. Find one which matches, and // return the type of the catch block which should be called. for (var i = 0; i < typeArray.length; i++) { - if (typeArray[i] && Module['___cxa_can_catch'](typeArray[i], throwntype, thrown)) { // XXX thrown should be an out ptr + if (typeArray[i] && Module['___cxa_can_catch'](typeArray[i], throwntype, thrown)) { + thrown = {{{ makeGetValue('thrown', '0', '*') }}}; // undo indirection {{{ makeStructuralReturn(['thrown', 'typeArray[i]']) }}}; } } // Shouldn't happen unless we have bogus data in typeArray // or encounter a type for which emscripten doesn't have suitable // typeinfo defined. Best-efforts match just in case. + thrown = {{{ makeGetValue('thrown', '0', '*') }}}; // undo indirection {{{ makeStructuralReturn(['thrown', 'throwntype']) }}}; }, diff --git a/system/lib/libcxxabi/src/private_typeinfo.cpp b/system/lib/libcxxabi/src/private_typeinfo.cpp index 8f873aec93c45..4e399d126b249 100644 --- a/system/lib/libcxxabi/src/private_typeinfo.cpp +++ b/system/lib/libcxxabi/src/private_typeinfo.cpp @@ -1162,13 +1162,15 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info, #ifdef __EMSCRIPTEN__ extern "C" { -int __cxa_can_catch(__shim_type_info* catchType, __shim_type_info* excpType, void *thrown) { +int __cxa_can_catch(__shim_type_info* catchType, __shim_type_info* excpType, void **thrown) { //std::type_info *t1 = static_cast(catchType); //std::type_info *t2 = static_cast(excpType); //printf("can %s catch %s (%p)?\n", t1->name(), t2->name(), thrown); - void *tempPtr = thrown; // XXX - return catchType->can_catch(excpType, tempPtr); + void *temp = *thrown; + int ret = catchType->can_catch(excpType, temp); + if (ret) *thrown = temp; // apply changes only if we are catching + return ret; } int __cxa_is_pointer_type(__shim_type_info* type) { diff --git a/tests/core/test_exceptions_virtual_inheritance.cpp b/tests/core/test_exceptions_virtual_inheritance.cpp new file mode 100644 index 0000000000000..647e26fdb469b --- /dev/null +++ b/tests/core/test_exceptions_virtual_inheritance.cpp @@ -0,0 +1,28 @@ +#include +#include + +using std::cout; +using std::endl; + +struct my_exception : public virtual std::runtime_error { + // To allow this to be thrown directly in the tests below. + explicit my_exception(const std::string &what) + : std::runtime_error(what) + {} + +protected: + my_exception() + // This won't be called because of virtual inheritance. + : std::runtime_error("::my_exception") + {} +}; + +int main(const int argc, const char * const * const argv) { + try { + cout << "Throwing ::my_exception" << endl; + throw ::my_exception("my_what"); + } catch(const std::runtime_error &ex) { + cout << "Caught std::runtime_error: " << ex.what() << endl; + } +} + diff --git a/tests/core/test_exceptions_virtual_inheritance.txt b/tests/core/test_exceptions_virtual_inheritance.txt new file mode 100644 index 0000000000000..ad1015d47c71f --- /dev/null +++ b/tests/core/test_exceptions_virtual_inheritance.txt @@ -0,0 +1,2 @@ +Throwing ::my_exception +Caught std::runtime_error: my_what diff --git a/tests/test_core.py b/tests/test_core.py index a955e3b0563b9..19bfb8680a7d4 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1463,6 +1463,17 @@ def test_exceptions_typed(self): self.do_run_from_file(src, output) + def test_exceptions_virtual_inheritance(self): + if self.emcc_args is None: return self.skip('requires emcc') + if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('needs fastcomp') + + Settings.DISABLE_EXCEPTION_CATCHING = 0 + + test_path = path_from_root('tests', 'core', 'test_exceptions_virtual_inheritance') + src, output = (test_path + s for s in ('.cpp', '.txt')) + + self.do_run_from_file(src, output) + def test_exceptions_multi(self): Settings.DISABLE_EXCEPTION_CATCHING = 0 test_path = path_from_root('tests', 'core', 'test_exceptions_multi')