diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs
index fbadf4ac6a0..268bafd2409 100644
--- a/src/libpanic_unwind/emcc.rs
+++ b/src/libpanic_unwind/emcc.rs
@@ -80,6 +80,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     extern "C" fn exception_cleanup(ptr: *mut libc::c_void) {
         unsafe {
             ptr::drop_in_place(ptr as *mut Exception);
+            super::__rust_drop_panic();
         }
     }
 }
diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs
index 6bec2686533..6e04317d491 100644
--- a/src/libpanic_unwind/gcc.rs
+++ b/src/libpanic_unwind/gcc.rs
@@ -78,6 +78,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     ) {
         unsafe {
             let _: Box<Exception> = Box::from_raw(exception as *mut Exception);
+            super::__rust_drop_panic();
         }
     }
 }
diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs
index 9451eefb9a5..6383ae39fb6 100644
--- a/src/libpanic_unwind/lib.rs
+++ b/src/libpanic_unwind/lib.rs
@@ -61,6 +61,12 @@ cfg_if::cfg_if! {
     }
 }
 
+extern "C" {
+    /// Handler in libstd called when a panic object is dropped outside of
+    /// `catch_unwind`.
+    fn __rust_drop_panic() -> !;
+}
+
 mod dwarf;
 
 // Entry point for catching an exception, implemented using the `try` intrinsic
diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs
index f1d0080472a..d9dca2c0f4f 100644
--- a/src/libpanic_unwind/seh.rs
+++ b/src/libpanic_unwind/seh.rs
@@ -229,6 +229,7 @@ macro_rules! define_cleanup {
         unsafe extern $abi fn exception_cleanup(e: *mut [u64; 2]) {
             if (*e)[0] != 0 {
                 cleanup(*e);
+                super::__rust_drop_panic();
             }
         }
         #[unwind(allowed)]
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 599ccc809be..43c2965f231 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -55,6 +55,14 @@ extern "C" {
     fn __rust_start_panic(payload: usize) -> u32;
 }
 
+/// This function is called by the panic runtime if FFI code catches a Rust
+/// panic but doesn't rethrow it. We don't support this case since it messes
+/// with our panic count.
+#[rustc_std_internal_symbol]
+extern "C" fn __rust_drop_panic() -> ! {
+    rtabort!("Rust panics must be rethrown");
+}
+
 #[derive(Copy, Clone)]
 enum Hook {
     Default,
diff --git a/src/test/run-make-fulldeps/foreign-exceptions/foo.cpp b/src/test/run-make-fulldeps/foreign-exceptions/foo.cpp
index ef5cd74c652..b0fd65f88e7 100644
--- a/src/test/run-make-fulldeps/foreign-exceptions/foo.cpp
+++ b/src/test/run-make-fulldeps/foreign-exceptions/foo.cpp
@@ -57,21 +57,4 @@ extern "C" {
             throw;
         }
     }
-
-    void swallow_exception(void (*cb)()) {
-        try {
-            // Do a rethrow to ensure that the exception is only dropped once.
-            // This is necessary since we don't support copying exceptions.
-            try {
-                cb();
-            } catch (...) {
-                println("rethrowing Rust panic");
-                throw;
-            };
-        } catch (rust_panic e) {
-            assert(false && "shouldn't be able to catch a rust panic");
-        } catch (...) {
-            println("swallowing foreign exception in catch (...)");
-        }
-    }
 }
diff --git a/src/test/run-make-fulldeps/foreign-exceptions/foo.rs b/src/test/run-make-fulldeps/foreign-exceptions/foo.rs
index d9818dffc50..9c2045c8c89 100644
--- a/src/test/run-make-fulldeps/foreign-exceptions/foo.rs
+++ b/src/test/run-make-fulldeps/foreign-exceptions/foo.rs
@@ -19,8 +19,6 @@ impl<'a> Drop for DropCheck<'a> {
 extern "C" {
     fn throw_cxx_exception();
 
-    fn swallow_exception(cb: extern "C" fn());
-
     #[unwind(allowed)]
     fn cxx_catch_callback(cb: extern "C" fn(), ok: *mut bool);
 }
@@ -61,34 +59,7 @@ fn throw_rust_panic() {
     assert!(cxx_ok);
 }
 
-fn check_exception_drop() {
-    static mut DROP_COUNT: usize = 0;
-
-    struct CountDrop;
-    impl Drop for CountDrop {
-        fn drop(&mut self) {
-            println!("CountDrop::drop");
-            unsafe {
-                DROP_COUNT += 1;
-            }
-        }
-    }
-
-
-    #[unwind(allowed)]
-    extern "C" fn callback() {
-        println!("throwing rust panic #2");
-        panic!(CountDrop);
-    }
-
-    unsafe {
-        swallow_exception(callback);
-        assert_eq!(DROP_COUNT, 1);
-    }
-}
-
 fn main() {
     unsafe { throw_cxx_exception() };
     throw_rust_panic();
-    check_exception_drop();
 }