<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - MSVC: noexcept aborts with longjmp"
   href="https://bugs.llvm.org/show_bug.cgi?id=36508">36508</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>MSVC: noexcept aborts with longjmp
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Windows NT
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>LLVM Codegen
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>alex@crichton.co
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org, rnk@google.com
          </td>
        </tr></table>
      <p>
        <div>
        <pre>This is a sort of roundabout bug with respect to where it originated from, but
the gist of it is that this program:





#include <assert.h>
#include <setjmp.h>
#include <stdio.h>

static jmp_buf ENV;

static void test_end() {
  longjmp(ENV, 1);
  assert(0);
}

static void test_middle() noexcept {
  test_end();
}

static void test_start() {
  if (setjmp(ENV) != 0)
    return;
  test_middle();
  assert(0);
}

int main() {
  test_start();
  printf("good\n");
  return 0;
}




will abort when compiled with Clang and succeed when compiled with cl.exe. More
specifically when compiled with `cl.exe foo.cpp /EHsc` the program will succeed
and print "good", but when compiled with `clang-cl.exe foo.cpp /EHsc` it will
instead abort.

I believe the issue here is that the `test_middle` function, declared with
`noexcept`, will abort thinking that it threw an exception. It appears that on
MSVC the `longjmp` function is implemented with an exception-like mechanism
which I believe triggers the landing pad generated by `test_middle` to abort
when an exception is thrown.

This bug actually came from an upstream Rust bug [1] which has quite a long
thread! The gist of it is that in Rust 1.24.0 we effectively turned on
`noexcept` for a certain class of Rust functions by default. This change
regressed on MSVC for us in that it broke users who wanted to longjmp across
Rust frames back to C (for example with other languages like Lua and Ruby).

I did some investigation to see what Clang did (as right now Rust's
exception-related MSVC codegen attempts to closely match what Clang does) and I
figured y'all may be interested in this as well! This may or may not be a bug
in
Clang (I'm not sure), so feel free to close if this isn't relevant for clang.

[1]: <a href="https://github.com/rust-lang/rust/issues/48251">https://github.com/rust-lang/rust/issues/48251</a></pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>