From 790bc408550277d222f8c2864a46c486ec0e9375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 19 Feb 2021 14:15:31 +0200 Subject: [PATCH] test: Add a testcase for throwing/catching C++ exceptions across DLLs --- Dockerfile.dev | 7 +++-- run-tests.sh | 13 +++++++-- test/throwcatch-lib.cpp | 40 +++++++++++++++++++++++++++ test/throwcatch-lib.h | 51 ++++++++++++++++++++++++++++++++++ test/throwcatch-main.cpp | 60 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 166 insertions(+), 5 deletions(-) create mode 100644 test/throwcatch-lib.cpp create mode 100644 test/throwcatch-lib.h create mode 100644 test/throwcatch-main.cpp diff --git a/Dockerfile.dev b/Dockerfile.dev index 0e4819a..852e9a3 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -91,8 +91,11 @@ RUN cd test && \ for test in hello-exception; do \ $arch-w64-mingw32-clang++ $test.cpp -static -o $arch/$test-static.exe || exit 1; \ done; \ - for test in tlstest-lib; do \ - $arch-w64-mingw32-clang++ $test.cpp -shared -o $arch/$test.dll || exit 1; \ + for test in tlstest-lib throwcatch-lib; do \ + $arch-w64-mingw32-clang++ $test.cpp -shared -o $arch/$test.dll -Wl,--out-implib,$arch/lib$test.dll.a || exit 1; \ + done; \ + for test in throwcatch-main; do \ + $arch-w64-mingw32-clang++ $test.cpp -o $arch/$test.exe -L$arch -l${test%-main}-lib || exit 1; \ done; \ done diff --git a/run-tests.sh b/run-tests.sh index 0e42717..c215ef5 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -67,7 +67,8 @@ TESTS_CPP="hello-cpp global-terminate" TESTS_CPP_LOAD_DLL="tlstest-main" TESTS_CPP_EXCEPTIONS="hello-exception exception-locale exception-reduced" TESTS_CPP_STATIC="hello-exception" -TESTS_CPP_DLL="tlstest-lib" +TESTS_CPP_DLL="tlstest-lib throwcatch-lib" +TESTS_CPP_LINK_DLL="throwcatch-main" TESTS_SSP="stacksmash" TESTS_ASAN="stacksmash" TESTS_UBSAN="ubsan" @@ -96,6 +97,9 @@ for arch in $ARCHS; do TEST_DIR="$arch" [ -z "$CLEAN" ] || rm -rf $TEST_DIR + # A leftover libc++.dll from a previous round will cause the linker to find it (and error out) instead of + # locating libc++.dll.a in a later include directory. + rm -f $TEST_DIR/libc++.dll mkdir -p $TEST_DIR for test in $TESTS_C; do $arch-w64-mingw32-clang $test.c -o $TEST_DIR/$test.exe @@ -144,7 +148,10 @@ for arch in $ARCHS; do TESTS_EXTRA="$TESTS_EXTRA $test" done for test in $TESTS_CPP_DLL; do - $arch-w64-mingw32-clang++ $test.cpp -shared -o $TEST_DIR/$test.dll + $arch-w64-mingw32-clang++ $test.cpp -shared -o $TEST_DIR/$test.dll -Wl,--out-implib,$TEST_DIR/lib$test.dll.a + done + for test in $TESTS_CPP_LINK_DLL; do + $arch-w64-mingw32-clang++ $test.cpp -o $TEST_DIR/$test.exe -L$TEST_DIR -l${test%-main}-lib done for test in $TESTS_SSP; do $arch-w64-mingw32-clang $test.c -o $TEST_DIR/$test.exe -fstack-protector-strong @@ -223,7 +230,7 @@ for arch in $ARCHS; do DLL="$DLL $i" fi done - RUN_TESTS="$TESTS_C $TESTS_C_LINK_DLL $TESTS_CPP $TESTS_EXTRA $TESTS_SSP" + RUN_TESTS="$TESTS_C $TESTS_C_LINK_DLL $TESTS_CPP $TESTS_CPP_LINK_DLL $TESTS_EXTRA $TESTS_SSP" cd $TEST_DIR if [ -n "$COPY" ]; then COPYFILES="" diff --git a/test/throwcatch-lib.cpp b/test/throwcatch-lib.cpp new file mode 100644 index 0000000..9b9fe02 --- /dev/null +++ b/test/throwcatch-lib.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Martin Storsjo + * + * This file is part of llvm-mingw. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "throwcatch-lib.h" +#include + +void libFunc(int param) { + switch (param) { + case 1: + fprintf(stderr, "throwing FirstException\n"); + fflush(stderr); + throw FirstException("first"); + case 2: + fprintf(stderr, "throwing SecondException\n"); + fflush(stderr); + throw SecondException("second"); + case 3: + fprintf(stderr, "throwing std::exception\n"); + fflush(stderr); + throw std::exception(); + default: + fprintf(stderr, "not throwing\n"); + break; + } +} diff --git a/test/throwcatch-lib.h b/test/throwcatch-lib.h new file mode 100644 index 0000000..d7440be --- /dev/null +++ b/test/throwcatch-lib.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 Martin Storsjo + * + * This file is part of llvm-mingw. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef THROWCATCH_LIB_H +#define THROWCATCH_LIB_H + +#include +#include + +class FirstException : public std::exception { +public: + FirstException(const char *s) : str(s) {} + + const char *what() const noexcept override { + return str.c_str(); + } + +private: + std::string str; +}; + +class SecondException : public std::exception { +public: + SecondException(const char *s) : str(s) {} + + const char *what() const noexcept override { + return str.c_str(); + } + +private: + std::string str; +}; + +void libFunc(int param); + +#endif diff --git a/test/throwcatch-main.cpp b/test/throwcatch-main.cpp new file mode 100644 index 0000000..250aaf3 --- /dev/null +++ b/test/throwcatch-main.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 Martin Storsjo + * + * This file is part of llvm-mingw. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "throwcatch-lib.h" +#include +#include + +int main(int argc, char* argv[]) { + int ret = 0; + for (int i = 0; i <= 3; i++) { + int caught = 0; + try { + libFunc(i); + } catch (FirstException &e) { + fprintf(stderr, "caught FirstException\n"); + caught = 1; + if (strcmp(e.what(), "first")) { + fprintf(stderr, "unexpected what()\n"); + ret = 1; + } + } catch (SecondException &e) { + fprintf(stderr, "caught SecondException\n"); + caught = 2; + if (strcmp(e.what(), "second")) { + fprintf(stderr, "unexpected what()\n"); + ret = 1; + } + } catch (std::exception &e) { + fprintf(stderr, "caught std::exception\n"); + caught = 3; + } catch (...) { + fprintf(stderr, "caught something else\n"); + caught = -1; + } + if (caught != i) { + fprintf(stderr, "caught unexpected exception!\n"); + ret = 1; + } + } + if (ret) + fprintf(stderr, "got errors\n"); + else + fprintf(stderr, "all ok\n"); + return ret; +}