<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/64471>64471</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Catching custom exceptions thrown from shared libraries fails when using -flto
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
ilg-ul
</td>
</tr>
</table>
<pre>
I have a failing test on the multi-platform [xPack LLVM/clang](https://github.com/xpack-dev-tools/clang-xpack/) when running on macOS.
It affects only macOS LTO builds, regular builds are fine. On GNU/Linux and MinGW-w64 the test passes.
The behaviour is the same on Apple clang version 14.0.0, xPack LLVM clang 15.0.7 and 16.0.6.
The code to run the test is:
```sh
mkdir ~/tmp/lto-throw-test
cd ~/tmp/lto-throw-test
cat <<'__EOF__' >throwcatch-lib.h
/*
* 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 <exception>
#include <string>
class FirstException : public std::exception {
public:
FirstException(const char *s) : str(s) {}
virtual 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) {}
virtual const char *what() const noexcept override {
return str.c_str();
}
private:
std::string str;
};
void libFunc(int param);
#endif
__EOF__
cat <<'__EOF__' >throwcatch-lib.cpp
/*
* 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 <stdio.h>
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;
}
}
__EOF__
cat <<'__EOF__' >throwcatch-main.cpp
/*
* 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 <string.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
int ret = 0;
for (int i = 0; i <= 3; i++) {
fprintf(stderr, "%d\n", 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, "\ngot errors\n");
else
fprintf(stderr, "\nall ok\n");
return ret;
}
__EOF__
echo "First test without -flto:"
clang++ throwcatch-lib.cpp -shared -fpic -o libthrowcatch-lib.dylib -std=c++11
clang++ throwcatch-main.cpp -o throwcatch-main -L. -lthrowcatch-lib -std=c++11
echo
./throwcatch-main
echo "Now test the same with -flto:"
clang++ throwcatch-lib.cpp -shared -fpic -o liblto-throwcatch-lib.dylib -std=c++11 -flto
clang++ throwcatch-main.cpp -o lto-throwcatch-main -L. -llto-throwcatch-lib -std=c++11 -flto
./lto-throwcatch-main
```
As shown in the copyright notices, the actual tests are from the [llvm-mingw](https://github.com/mstorsjo/llvm-mingw) project, by @mstorsjo.
The output I get on a macOS 12.6.7 with CLT installed is:
```console
First test without -flto:
0
not throwing
1
throwing FirstException
caught FirstException
2
throwing SecondException
caught SecondException
3
throwing std::exception
caught std::exception
all ok
Now test the same with -flto:
0
not throwing
1
throwing FirstException
caught std::exception
caught unexpected exception!
2
throwing SecondException
caught std::exception
caught unexpected exception!
3
throwing std::exception
caught std::exception
got errors
```
As it can be seen, `FirstException` and `FirstException` are caught as `std::exception`. Without `-flto`, they are caught as expected.
Is this a bug or am I missing something when using LTO?
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWl9vqzoS_zT0ZRRETJO2D32gCTRIaegGeqr7VDlggu8hNrJNevqyn31lQxLyp2lvz5F2tSqKEsCemZ9_tmfGdrCUdMkIubUGd9ZgfIFrVXBxS8tlry4vFjx7uw2hwGsCGHJMS8qWoIhUwBmogsCqLhXtVSVWORcrsAZ3vx5x-hOm0x8PFgrSErOlNRhb6LpQqpKW61kosFCwpKqoF3bKVxYKflU4_dnLyLqnOC_lRq5n3pv6N_BaEAaiZkwj4AxWOI1i23LGluM136ECnOckVRI4K9-aGjBNIljUtMykhUYgyLIusWjfABYEcsqIDRGD-9mThYIpZfUvwCyDB8run3uvw0vTUNPoCktJ5J7VpCCwIAVeU14LoNJUlnhFNEivqkoCpjGwJkJSzqB_aTu2o8HsmGqr9Ae2Y18Z4_2h7djDI0spzwgoronYoaKG1k5Na-g0H1k0L1Y_Myrg3xYK1KqyUFAq3lOF4K89raCpk2YfVGirYQWWO9IfdPXy4kfBy4uFrsByfSOQYpUWvZIu7Na26b9WGCzkwYhXb4IuCwUWuk513yIH9eEBC0UZxIoL-Tff1e9IJgWVkNOSaJ4rLBTwHMpyveqtKFu-2ieFHolYUWmoVxxqSTT1Ka_e9O-KZzQ3d5hlFgq4gIxKJeiiVgSUtid5rl7NQOECMHvrqK5qUXFJ4JWqArgwv7xWkBODsCCCLN5gKTBTJNNGKsHXNCMZqAIr04F4wdekozLdksO4oikxg8HgqHbt2BRVFcECKANcllqSbsfmIXETH-IoSJ69uQ9hDI_z6Ec49sdgIeTFEMYWQuDNxqai95RMojmMw3g09cKHGLzpFJ69-dybJaEfd9Q-h8kE5v69Nx9DEkEyCeOOmdlo-jQOZ_dGPnx4nIb-uKMHoqCj6sGfjybeLPHuwmmY_GXABGEy8-PYhnAGswj8H_4sgXii1XVw3vkwDb27qQ9BNO9o9GZ_Qfzoj0Jvqqkfh3N_lOi7cLa7j-Ywimax_68nf5aE3hTG3oN3r8HNjYL2sdvmiZfEkf_Dn8Pcj5-miW5hMI8eYBrFulHwFPvGoJd4Ws3jPArCJNavnid-MvHnuj3erAt1lITRTMuOolky9xpsM_9-Gt77s5Gv1URGMonmSRg9xa2IrubNw1hjiJ6SfUojY2gUzWZ-o990l2buKTYqH_15EM0fPGMh2O--7jhCwZ5zQS7NWUZySCbz6HnkJaPJyzS8e5lsyzOinep75VstLC3rjGhvQn6lpFKUM8v1T5XrGcmWu8LGE5VYSgiokMrfyIPl6mm5KGkKUmXaL7oe2ZVe3TWyTZWt2zzQov0SZ1JBWmChKZDaS2nVUgkLXTePV3fW1bgLCABgTYWqsZ6NXfnXAisLXWuxpoDxBhTwNRGC6lZuoEF7CaJqwbRFO31p7FroxnI31Q6MV4KusSK7JgHsGGj4M-g38lp8e9_hMyYpZ9lvEwpwqOm_S-pHbAL8eULXnGZQ0kVQs9RC15TpBELgVdfwdrQTltG8edpE1S9F3bSqvuPud9z9jrv_j3F3ExEROsq1ETodODPK7eIgcp5xTPtxSL5SlRbaX5wuT7Ek0N-5yLwSlKlce3OVESE0Txuw2l8ehNnBiGncXT-c52Uti46CfR-tL6PtOGJbCOX63aHGDUy058n19RHawwD2O3CPg6GFkDQv3wPs_mPAxwH6tzCfUHccNTOS47pUH44BxhVsgJ5C1V4LQfDPU0nO5ubLwXGFKfuOjt_R8Ts6fkfHvWVlNzx-InjqaKl9SRs4sVimZu4WWOj2YbFcN3upR9FSVxdE-6oxOHueT0_iVh_dFpvbkX5yzZOF7szn5nit-I7PtdAg2_rakdZw7HC1zRTXxvEd4TKxQLwdG9RXJ4E4pdi6GoPpAt2yw1U6GpKTDTnTmBbkxylE5-o0rH-yAs3B2BHpqrLQNbF3i8rWbDeneA_xGdQ1I78qkiqSQUf1edTt6v8M7G003Gf5aO3-dZo_kfuc5hl9kee9XOh_nehTOyFf5_pzadtput3z88627a-C4iuiCp1VklKSU4A6KHrH7O2Y2xsCGyHU13J0H9x5RJ0e7iSk_Q-4er9_9xDuPTRQBVFa6acc7WDEllwBEYIL-Q4iw-Nntencif88pandydLoultP7yXHJC24Vmr8ZnNetEkIe3mpuDmRQwf7gGzZBBs43lyCniywIBn08oqm0OM6DhxUy95KuoCeGdfjtFHV75_VvsnOtcKD19Cb2tAr9228o33X5u6zbaHgQOkpimb8tSFoe4RnUug_R9P2VO0jqlqbnyXsQG-HtGOLZ23t6Dqhsq2yOVvsSngSZMFfmc76lTmm3F8vmLNXs7BIzUauZrk9fRV8ZUqswd1uzfThifFKtgsyFHSk0I1ey_xNUqXtLd7AunQ2NY-OUnmtqlpBCEtiTrNxe2DcR_bQvmq6fjRNgDKpcFmS7Mw5a8qZ5GU7u8_NtI5wS-Deuti8aYfye5sm7ZL3VDJkitCB-GEk78qfLHMPFJwIT10d7xU3360f67z5aJb9MXI-wP1eOPnHJP6OnT_KdScCnZqqsJ2rVKf8DBYEJCHMRJ2hc8Dk0DGL_NMFgmyiP5a6yglcQ8eG53b4W0On6d6h0zqCtwMdG4r2_9Ahmz0GDIt6CVwAXkEIZrtBU7VNUMxfQ2rzcppElru_MOx8X2S3bnbj3uALctsf3vRd1B8Mri-K2zx3sJPhQba4SvHgZkCQ279O3UvHzfObhTu4oLfIQa5z7Qz7fRe513aGsHOT9l2U3lz1U4SsS4esMC1t7Y5sLpYXVMqa3A4vL6_6FyVekFKa_9ggxMgrmEIT6scX4ta4sEW9lNalU1Kp5E6LoqoktyPthHX70loqvtoNJNlMD9b40TbklHQhsKBEmn_syC4_phvgohbl7Rnvqq1vPOvWoQYGs7RQYNr0nwAAAP__ppx49g">