<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/59690>59690</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Issue throwing an exception within a varargs function on x86 Windows with inlining enabled
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          dunhor
      </td>
    </tr>
</table>

<pre>
    I've come across an issue that _appears_ to be caused by bad code-gen on Windows when building an x86 binary. I've been unable to narrow down and isolate the exact underlying cause of the issue in the form of a minimal repro, but it can easily be reproduced using the steps described below. That said, by process of elimination, it seems specific to throwing an exception from within a varargs function. I say that it seems specific to varargs because a virtually equivalent line of code immediately preceding the offending one copied below has no issues, but throws from within a non-varargs function. The first line that causes the issue is the following, which can be seen [here](https://github.com/microsoft/wil/blob/033be929ee93ef394f6a8783f19b7d6256e063c1/tests/wiTest.cpp#L760):
```c++
 REQUIRE_THROWS_MSG(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; THROW_IF_NULL_ALLOC_MSG(MDEC(pInt), "msg: %d", __LINE__); });
```
In this case, the varargs function called by the macro expansion of `THROW_IF_NULL_ALLOC_MSG` will (eventually) throw an exception, and then during stack unwind, the destructor for `pInt` will trigger a debug break inside of the call to `free`. This happens because the memory on the stack for `pInt` has been corrupted and so the memory trying to be free'd is invalid (it should be a null pointer, of course). Before diving into that, it might better help to inline some macro expansion so it's easier to see what's being dealt with:
```c++
REQUIRE(VerifyResult(__LINE__, EType::Msg, E_OUT_OF_MEMORY, [&] {
    return TranslateException([] {
 std::unique_ptr<int> pInt;
        THROW_IF_NULL_ALLOC_MSG(MDEC(pInt), "msg: %d", __LINE__);
    });
}));

...

template <typename TLambda>
HRESULT TranslateException(TLambda&& lambda)
{
 try
    {
        lambda();
    }
    catch (wil::ResultException &re)
    {
        return re.GetErrorCode();
 }
#ifdef __cplusplus_winrt
    catch (Platform::Exception ^pe)
 {
        return wil::details::GetErrorCode(pe);
    }
#endif
 catch (...)
    {
        FAIL();
    }
    return S_OK;
}
```
So effectively, `TranslateException` is calling a lambda (that gets inlined) that has a `unique_ptr` local and calls a varargs function (that does not get inlined) that unconditionally throws an exception (it's test code). I captured a TTD trace that I can share out if needed, and after analyzing it some, it looks like the memory "owned" by the `unique_ptr` gets written to inside of `BuildCatchObjectHelperInternal<__FrameHandler3>`. It seems to be writing a pointer to the exception (or the exception itself I don't exactly recall), setting up for the invocation of the `catch (wil::ResultException&)` handler inside of `TranslateException`. This would bring me to the conclusion that the calculation of the address is wrong, which means that either the registration node has the wrong address, or the handler offset is incorrect. I lack the expertise or insight to know which one it might be. For reference, the calculation of this address is:
```c++
pCatchBuffer = (void**)OffsetToAddress(
    HT_DISPATCH(*pCatch),
 (EHRegistrationNode*)pRN);
```
As for reproing the issue, I've created a branch that has the issue [here](https://github.com/microsoft/wil/tree/dunhor/clangbug). After cloning, in an x86 VS tools command window (I'm using 2022, but presumably it won't matter I wouldn't think), you can reproduce the issue by running:
1. `c:\wil> scripts\init.cmd -b relwithdebinfo`
2. `c:\wil> cd build\clang32relwithdebinfo`
3. `c:\wil\build\clang32relwithdebinfo> ninja`
4. `c:\wil\build\clang32relwithdebinfo> tests\normal\witest.exe`

That should cause the issue to repro. If you don't have a postmortem debugger enabled, you might need to run step (4) under the debugger. You can also probably save some time by scoping step 3 down to `ninja witest` I'd assume. Installed Clang version is `clang version 15.0.6`. It's also worth noting that I first noticed this issue after testing a `Release` build, which we rarely do; we use `RelWithDebInfo` by default, however this does _not_ crash. The important difference seems to be CMake's insistence on compiling with `/Ob1` for `RelWithDebInfo`, instead of `/Ob2`, the more sensical option. The branch I linked to replaces `/Ob1` with `/Ob2` for non-`Debug` builds.

Let me know if there's any additional info I can give!
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJysWF1z2zaz_jXwzU40NBjR0oUvbFlqNMeJe2ynnV5pQHIpoQYBFgCl6Pz6M7sg5Y84yTudt-PaIUEs9vPZZ6FC0FuLeCmm12J6c6b6uHP-su7tzvmz0tXHy7WQF3uEyrUIqvIuBFAWdAg9QtypCBvVdah82EB0UCJUqg9YQ3mEUtVQuRo_bNGCs_CntrU7BDjs0ELZa1NruyVp32YFlNoqf5zAcF6JaKG3qjRIcq3y3h2gdgcLytaggzMqkgYI-E1VEXpbozdHksgagGt4NWmqLT80zre0oKDVVrfKgMfOOyEXUPYRdIRKWUAVtDmSLbxa9xXW0AcSTUJCxC5AjaHyuiRL0bjDBB7JGUHpmqUdofOuwhDoODS61VZF7Swt6ggBsQ0QOqx0oyuyMO68Owz-wG8VdvQ1NN61cNBxpy0o2Cuv_DZA09uKliewhqCOKQ7vSh13lJicomCvfeyVMUfAf3q9VwZtBKMtO4yiBbptsdYqoiEjsMJ6tNw1DVp-cpZSotOj-bBTAaxL3g6jP9mm8MYI6-yH7w15pOhoHwZd2CJWObyMYhiiaAz7is457HS147CVSA6wIKbXO_QopjdCznYxdkHkV0KuhFxtddz15aRyrZCrVlM6uyYKuTpoI-SqNK4UcpXleYlzOUec59jk849NoWYXs7w5n5cXdSGnBWZFXp0LuYoYYuD9jxjipOo6IfPbiyITck6nZjciuxJFln4qIa_ph9_C_fJ_v67vl5vHT_d3fz5sPj_8JuRsubn7-ni3-rz8fHf_F9mXKhPExTWEWJPM_Kq3-p8eN130Il9oG0W-hG5Nf6-BpW3Wq82Xr7e3m6vb27vFIPrzzXIh5Iw_lHOWLWUbtiK_AiGntZCSXm42t-svy82GLbgGcXGT_vXGlvS4prrSASoVkDZTeN4GFyplTEIEWm4JRQC_dcoGWnUNiCL7kdpFBgdtDAg5wz3alLpCzlNuvSoWOp-wIRK81L2nPA1RVU_Q24O29ahfjSH6vorOEx7Q4eyS8aTo9XaLHhTUWPZbKD2qJ9A26PoEKmQRlZcossYjiiKjDNYBdgSG9rne2GBsnT8SACb0II3eHEzVw4hXOe_7LmLNlgT3UkD0jG4JZflYeUFICNruldE1-YhAYOd6Q2VJtdYbA53TNqIn87nEe0-xmk_gGhvnEWq9J7naMgqpOEBUq7e7CCXGiB52aDo6WVsuz0Dd4G0ggwMdhbwIDKDo6fuACAeWeUEW0jk1KhMZDn5RIEN9CDn7A71ujvcYehOFnD1n6AKWj8cOU1V8DgwIXEGbu9XmdQ3JYiijofoAwGPsvYVHr2ygbrJ8zqTZc9kN3_8nxfcsmv77L1fis_C3JZkeX77h35PJ5OVjxLbjninyRTx2aFWL8Hir2rJWIl-mjz7dLx--3j6-75PxY1kIWYAZHuajFqOG0R9f6vrGK-O22XtWnR4qFasdJTQBM7s9Rf-kDghZeDyd_u5RQ3w9Tn7DuPTe-YWr8e3Rp3OFzHVTYwObTdWZPtD_m4O2Pr6j1-9GRWITSbkXak2X3Qu1fqTTyawao9ImpIc3aiZB7_pIyJw6cTMsndSimP_UJ6ur9e2vnD_o-LC5-59XSfZeA3hwgE2DVdR7JGBeMJh_nz1FBtwmjGGOM6QBqcytfosxDOBSJ3RXkVFRkbwXJVdkYFylDOMjiQvv8KKT2Noh0RKW_5343lbO1po2MB8a2Mor_sWQyuBFnZ75EUPnGirVxd4TUMPj4w1Er6qBtqyZjYSd8giOWGUDFrHGemxQqiFIVVaZ4_8x8kYG1AF3jXNPAYx-etU9hJTuwNrLsZF-5xh24sHrGNEmsB57liiya-LbC8qTu_JvrOInNB36NXUGq4zIF5vNyqsWPylbG_Q5QQK1tfVIK1PfIfEpgkNbSdwVX_vM-TfvdAxoGlhDTUhyERNpN0fwSEEcUDBgZOF9xw2SiZ_du4qZ89h7qU38Ch0Youaps7I5r33xbn4OHfyQuiezhxZH6ypnK9Nzm-MYDySg6s0r3VRde-L8JMe7lwS1RWVD2os67jBZ53GrQ_RJhiXyTTlPK7x9lMetO-0Y7XFNEyinqWqINGAVKSsNkYvk-g591DQHJeOpmUcHT9YdBpWIw7_o8xNYOQ8eG_RoqxOb-85KHV6Y-YsW3nHCXfdNgx5EfkMx2zsaka74Z37HZjy6q9HQ2TMMfXrc3Kwffr96XHxixBqkpVwZ8VXOlp_uX3jxC1coie7uv_yEuF4FTjEe8MbxhocMsnuceT0qpmJQemWr3TMqPY8k_37YiMzgVmnWFnJVGWW3Zb9lfLliiKiMs8OYQ6NTGpT_eIDonAk0krcEJwceq8kVpHc7TKoySySC5rDOY-hbVZojBfwwlGCrmNqtU8qndzSjPQ3VeHQ9I9lpCH5hdnkE31tWbsyA8wmXJj1PF1yYS6ARuYtBTBfa6jip2ho-lODREP2rsdS2caeQyHcEVHW6KBDTBfsnlz_YnL_dPF38fGO-BKvt3-ok4eO_kJDGv-nCOt8qw_vo1QS_4Ulu-p1uBxI1fx4NhmsUl3w8gXXDXh9Bcqf2yEgbYut8xDaNJDSdIF-N1GOcUhFTm2FpveVbCsqJj9Tv-HJkGH6SgAn8NYRXmeCg867k_Ah0JNP7qFuOc6A5n0cp7CBPVzBp9GH_QTKZsHbNA4kKoW9xAmsbYhr8FuQ-2KNn_NSB_fzq3fl0kk2Kod9wu2WtDs7HHfXvVKHcW9MlAb2ryFiCo-TF1FVJl9SfRJHdo0EaTItsyKITHB8QvPJojlA7mnIPCBSTtOdPHXc3WK5TfpEPamwUzx4L2LkD7tmZOiR-sbEubqDyKuzSPYZuO-ejshFq3Qxw-qqJLj6rJ2QzCZlD5A9oUHZtp5kgUZ6RNkKu7spz0mKYGL9TL4FDiKjqobvxHjksMYWgKS-gDZqIk-ueb1wGXFuD0fZpyB3sjKowvD79lT5y1Mc6-0EU2Q3l1MnJ4dXUcYuR2ii3Hc1N0ifLlT1SHxnoF1BFDcxpq_co5PlZfZnX83yuzvDyvLg4nxX5xzw_212q86LMZvOpnGXltCjPVSlnWMhpkxVqmsn8TF8S-J1L-TEr8izPJ1kxK6eNPG_keSZlMRUfM2yVNhNj9u3E-e0Zp9DldF7MszOjSjRhvBL1l_TRh7LfBvExMzrE8Lwt6mjwcj1chr53gffDuzuKN8H56VKUPMwUlWQM5X3We3P5k65Cigx_PnTeEa8TcjVewq3Ynv8PAAD__-YnEng">