Skip to content

Commit 0e05ab9

Browse files
authored
Auto-export setThrew for emscripten exceptions (#14153)
Normally if exceptions are enabled, we have exceptions thrown and caught etc., and they will depend on setThrew. And then we will link it in. However, if the code only contains invokes, but no exception catching, then there is no library support that tells us to include it. To fix that, always include the function when emscripten exceptions are enabled. I don't think this can regress code size, as setThrew will almost certainly be used anyhow, unless there are also no invokes at all. And in that case, metadce can remove it. Fixes #14078
1 parent fa311fa commit 0e05ab9

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

emcc.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2168,10 +2168,18 @@ def check_memory_setting(setting):
21682168
settings.EXPORTED_FUNCTIONS += ['_malloc', '_free']
21692169

21702170
if not settings.DISABLE_EXCEPTION_CATCHING:
2171-
# If not for LTO builds, we could handle these by adding deps_info.py
2172-
# entries for __cxa_find_matching_catch_* functions. However, under
2173-
# LTO these symbols don't exist prior the linking.
2174-
settings.EXPORTED_FUNCTIONS += ['___cxa_is_pointer_type', '___cxa_can_catch']
2171+
settings.EXPORTED_FUNCTIONS += [
2172+
# If not for LTO builds, we could handle these by adding deps_info.py
2173+
# entries for __cxa_find_matching_catch_* functions. However, under
2174+
# LTO these symbols don't exist prior the linking.
2175+
'___cxa_is_pointer_type',
2176+
'___cxa_can_catch',
2177+
2178+
# Emscripten exception handling can generate invoke calls, and they call
2179+
# setThrew(). We cannot handle this using deps_info as the invokes are not
2180+
# emitted because of library function usage, but by codegen itself.
2181+
'_setThrew',
2182+
]
21752183

21762184
if settings.ASYNCIFY:
21772185
if not settings.ASYNCIFY_IGNORE_INDIRECT:

tests/test_other.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9242,6 +9242,30 @@ def test_f_exception(self, compile_flags, link_flags, expect_caught):
92429242
result = self.run_js('a.out.js', assert_returncode=0 if expect_caught else NON_ZERO)
92439243
self.assertContainedIf('CAUGHT', result, expect_caught)
92449244

9245+
def test_exceptions_with_closure_and_without_catching(self):
9246+
# using invokes will require setThrew(), and closure will error if it is not
9247+
# defined. this test checks that we define it even without catching any
9248+
# exceptions (if we did catch exceptions, that would include library code
9249+
# that would use setThrew() anyhow)
9250+
create_file('src.cpp', r'''
9251+
#include <stdio.h>
9252+
#include <emscripten.h>
9253+
9254+
struct A {
9255+
~A() {
9256+
puts("~A");
9257+
}
9258+
};
9259+
9260+
int main() {
9261+
// Construct an instance of a class with a destructor, which will cause the
9262+
// use of invokes to ensure its destructor runs.
9263+
A a;
9264+
throw 5;
9265+
}
9266+
''')
9267+
self.run_process([EMCC, 'src.cpp', '-fexceptions', '--closure=1'])
9268+
92459269
def test_assertions_on_internal_api_changes(self):
92469270
create_file('src.c', r'''
92479271
#include <emscripten.h>

0 commit comments

Comments
 (0)