Fail at link time if exception catching is enabled at compile time but not link time (#13862)
This commit is contained in:
Родитель
e51a23f2cc
Коммит
da39727384
|
@ -143,6 +143,7 @@ var LibraryExceptions = {
|
|||
return {{{ makeGetValue('this.ptr', 'ptrSize', '*') }}};
|
||||
};
|
||||
|
||||
#if !DISABLE_EXCEPTION_CATCHING
|
||||
// Get pointer which is expected to be received by catch clause in C++ code. It may be adjusted
|
||||
// when the pointer is casted to some of the exception object base classes (e.g. when virtual
|
||||
// inheritance is used). When a pointer is thrown this method should return the thrown pointer
|
||||
|
@ -170,6 +171,7 @@ var LibraryExceptions = {
|
|||
} else {
|
||||
this.ptr = ptr;
|
||||
}
|
||||
#endif
|
||||
},
|
||||
|
||||
$exception_addRef: function (info) {
|
||||
|
@ -287,6 +289,7 @@ var LibraryExceptions = {
|
|||
return type;
|
||||
},
|
||||
|
||||
#if !DISABLE_EXCEPTION_CATCHING
|
||||
__cxa_begin_catch__deps: ['$CatchInfo', '$exceptionCaught', '$exception_addRef',
|
||||
'$uncaughtExceptionCount'],
|
||||
__cxa_begin_catch: function(ptr) {
|
||||
|
@ -336,6 +339,7 @@ var LibraryExceptions = {
|
|||
#endif
|
||||
return new CatchInfo(ptr).get_exception_ptr();
|
||||
},
|
||||
#endif
|
||||
|
||||
__cxa_uncaught_exceptions__deps: ['$uncaughtExceptionCount'],
|
||||
__cxa_uncaught_exceptions: function() {
|
||||
|
@ -371,6 +375,7 @@ var LibraryExceptions = {
|
|||
___cxa_rethrow();
|
||||
},
|
||||
|
||||
#if !DISABLE_EXCEPTION_CATCHING
|
||||
// Finds a suitable catch clause for when an exception is thrown.
|
||||
// In normal compilers, this functionality is handled by the C++
|
||||
// 'personality' routine. This is passed a fairly complex structure
|
||||
|
@ -380,7 +385,7 @@ var LibraryExceptions = {
|
|||
// unwinding using 'if' blocks around each function, so the remaining
|
||||
// functionality boils down to picking a suitable 'catch' block.
|
||||
// We'll do that here, instead, to keep things simpler.
|
||||
__cxa_find_matching_catch__deps: ['$exceptionLast', '$ExceptionInfo', '$CatchInfo', '__resumeException'],
|
||||
__cxa_find_matching_catch__deps: ['$exceptionLast', '$ExceptionInfo', '$CatchInfo', '__resumeException', '__cxa_can_catch'],
|
||||
__cxa_find_matching_catch: function() {
|
||||
var thrown = exceptionLast;
|
||||
if (!thrown) {
|
||||
|
@ -440,8 +445,26 @@ var LibraryExceptions = {
|
|||
catchInfo.free();
|
||||
{{{ makeThrow('ptr') }}}
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#if DISABLE_EXCEPTION_CATCHING
|
||||
[
|
||||
'__cxa_begin_catch',
|
||||
'__cxa_end_catch',
|
||||
'__resumeException',
|
||||
'__cxa_find_matching_catch',
|
||||
'__cxa_get_exception_ptr',
|
||||
].forEach(function(name) {
|
||||
LibraryExceptions[name] = function() { abort(); };
|
||||
#if !INCLUDE_FULL_LIBRARY
|
||||
LibraryExceptions[name + '__deps'] = [function() {
|
||||
error('DISABLE_EXCEPTION_CATCHING was set, which means no C++ exception catching support code is linked in, but such support is required by symbol `' + name + '`. Either link with DISABLE_EXCEPTION_CATCHING=0 (if you do want exception catching) or compile all source files with DISABLE_EXCEPTION_CATCHING=1 (the default) (so that no exception catching support code is required).');
|
||||
}];
|
||||
#endif
|
||||
});
|
||||
#else
|
||||
// In LLVM, exceptions generate a set of functions of form __cxa_find_matching_catch_1(), __cxa_find_matching_catch_2(), etc.
|
||||
// where the number specifies the number of arguments. In Emscripten, route all these to a single function '__cxa_find_matching_catch'
|
||||
// that variadically processes all of these functions using JS 'arguments' object.
|
||||
|
@ -450,5 +473,6 @@ addCxaCatch = function(n) {
|
|||
LibraryManager.library['__cxa_find_matching_catch_' + n + '__sig'] = new Array(n + 2).join('i');
|
||||
LibraryManager.library['__cxa_find_matching_catch_' + n + '__deps'] = LibraryExceptions['__cxa_find_matching_catch__deps'];
|
||||
};
|
||||
#endif
|
||||
|
||||
mergeInto(LibraryManager.library, LibraryExceptions);
|
||||
|
|
|
@ -7210,7 +7210,7 @@ int main() {
|
|||
self.assertEqual(wasm_data.count(b'dylink'), 1)
|
||||
|
||||
@is_slow_test
|
||||
def test_wasm_backend_lto(self):
|
||||
def test_lto(self):
|
||||
# test building of non-wasm-object-files libraries, building with them, and running them
|
||||
|
||||
src = test_file('hello_libcxx.cpp')
|
||||
|
@ -7243,10 +7243,10 @@ int main() {
|
|||
self.assertContained('hello, world!', self.run_js('a.out.js'))
|
||||
|
||||
@parameterized({
|
||||
'except': [],
|
||||
'noexcept': ['-s', 'DISABLE_EXCEPTION_CATCHING=0']
|
||||
'noexcept': [],
|
||||
'except': ['-s', 'DISABLE_EXCEPTION_CATCHING=0']
|
||||
})
|
||||
def test_wasm_backend_lto_libcxx(self, *args):
|
||||
def test_lto_libcxx(self, *args):
|
||||
self.run_process([EMXX, test_file('hello_libcxx.cpp'), '-flto'] + list(args))
|
||||
|
||||
def test_lto_flags(self):
|
||||
|
@ -9127,7 +9127,17 @@ int main(void) {
|
|||
self.assertGreater(enable_size, disable_size)
|
||||
self.assertEqual(disable_size, ignore_size)
|
||||
|
||||
def test_f_exception(self):
|
||||
@parameterized({
|
||||
# exceptions are off by default
|
||||
'off': ([], [], False),
|
||||
# enabling exceptions at link and compile works
|
||||
'on': (['-fexceptions'], ['-fexceptions'], True),
|
||||
# just compile isn't enough as the JS runtime lacks support
|
||||
'compile_only': (['-fexceptions'], [], False),
|
||||
# just link isn't enough as codegen didn't emit exceptions support
|
||||
'link_only': ([], ['-fexceptions'], False),
|
||||
})
|
||||
def test_f_exception(self, compile_flags, link_flags, expect_caught):
|
||||
create_file('src.cpp', r'''
|
||||
#include <stdio.h>
|
||||
int main () {
|
||||
|
@ -9139,21 +9149,15 @@ int main(void) {
|
|||
return 0;
|
||||
}
|
||||
''')
|
||||
for compile_flags, link_flags, expect_caught in [
|
||||
# exceptions are off by default
|
||||
([], [], False),
|
||||
# enabling exceptions at link and compile works
|
||||
(['-fexceptions'], ['-fexceptions'], True),
|
||||
# just compile isn't enough as the JS runtime lacks support
|
||||
(['-fexceptions'], [], False),
|
||||
# just link isn't enough as codegen didn't emit exceptions support
|
||||
([], ['-fexceptions'], False),
|
||||
]:
|
||||
print(compile_flags, link_flags, expect_caught)
|
||||
self.run_process([EMCC, 'src.cpp', '-c', '-o', 'src.o'] + compile_flags)
|
||||
self.run_process([EMCC, 'src.o'] + link_flags)
|
||||
result = self.run_js('a.out.js', assert_returncode=0 if expect_caught else NON_ZERO)
|
||||
self.assertContainedIf('CAUGHT', result, expect_caught)
|
||||
self.run_process([EMCC, 'src.cpp', '-c', '-o', 'src.o'] + compile_flags)
|
||||
if compile_flags and not link_flags:
|
||||
out = self.expect_fail([EMCC, 'src.o'] + link_flags)
|
||||
self.assertContained('error: DISABLE_EXCEPTION_CATCHING was set, which means no C++ exception catching support code is linked in, but such support is required by symbol `__cxa_begin_catch`.', out)
|
||||
return
|
||||
|
||||
self.run_process([EMCC, 'src.o'] + link_flags)
|
||||
result = self.run_js('a.out.js', assert_returncode=0 if expect_caught else NON_ZERO)
|
||||
self.assertContainedIf('CAUGHT', result, expect_caught)
|
||||
|
||||
def test_assertions_on_internal_api_changes(self):
|
||||
create_file('src.c', r'''
|
||||
|
|
Загрузка…
Ссылка в новой задаче