about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAmanieu d'Antras <amanieu@gmail.com>2020-03-21 07:50:38 +0000
committerAmanieu d'Antras <amanieu@gmail.com>2020-08-27 21:08:30 +0100
commit239f833ed1842ce7ce5c9989871a9ce9b1ea3546 (patch)
tree78aa987848dfbed8edd6def955ab5625acc1ef17 /src
parent118860a7e76daaac3564c7655d46ac65a14fc612 (diff)
Abort when catch_unwind catches a foreign exception
Diffstat (limited to 'src')
-rw-r--r--src/librustc_codegen_llvm/context.rs21
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs136
-rw-r--r--src/librustc_hir/weak_lang_items.rs1
-rw-r--r--src/librustc_middle/middle/lang_items.rs4
-rw-r--r--src/librustc_passes/weak_lang_items.rs3
-rw-r--r--src/librustc_span/symbol.rs1
-rw-r--r--src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs2
-rw-r--r--src/test/run-make-fulldeps/foreign-exceptions/foo.cpp6
-rw-r--r--src/test/run-make-fulldeps/foreign-exceptions/foo.rs21
-rw-r--r--src/test/run-make-fulldeps/issue-69368/a.rs5
-rw-r--r--src/test/ui/consts/const-eval/const_panic_libcore_main.rs2
-rw-r--r--src/test/ui/macros/macro-comma-behavior.core.stderr14
-rw-r--r--src/test/ui/macros/macro-comma-behavior.rs1
-rw-r--r--src/test/ui/macros/macro-comma-behavior.std.stderr20
-rw-r--r--src/test/ui/no_owned_box_lang_item.rs1
-rw-r--r--src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs2
-rw-r--r--src/test/ui/range/issue-54505-no-std.rs3
-rw-r--r--src/test/ui/range/issue-54505-no-std.stderr12
18 files changed, 194 insertions, 61 deletions
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 26707fdf839..1c51a9df5d8 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -82,6 +82,7 @@ pub struct CodegenCx<'ll, 'tcx> {
     pub dbg_cx: Option<debuginfo::CrateDebugContext<'ll, 'tcx>>,
 
     eh_personality: Cell<Option<&'ll Value>>,
+    eh_catch_typeinfo: Cell<Option<&'ll Value>>,
     pub rust_try_fn: Cell<Option<&'ll Value>>,
 
     intrinsics: RefCell<FxHashMap<&'static str, &'ll Value>>,
@@ -311,6 +312,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
             coverage_cx,
             dbg_cx,
             eh_personality: Cell::new(None),
+            eh_catch_typeinfo: Cell::new(None),
             rust_try_fn: Cell::new(None),
             intrinsics: Default::default(),
             local_gen_sym_counter: Cell::new(0),
@@ -819,6 +821,25 @@ impl CodegenCx<'b, 'tcx> {
         }
         None
     }
+
+    crate fn eh_catch_typeinfo(&self) -> &'b Value {
+        if let Some(eh_catch_typeinfo) = self.eh_catch_typeinfo.get() {
+            return eh_catch_typeinfo;
+        }
+        let tcx = self.tcx;
+        assert!(self.sess().target.target.options.is_like_emscripten);
+        let eh_catch_typeinfo = match tcx.lang_items().eh_catch_typeinfo() {
+            Some(def_id) => self.get_static(def_id),
+            _ => {
+                let ty = self
+                    .type_struct(&[self.type_ptr_to(self.type_isize()), self.type_i8p()], false);
+                self.declare_global("rust_eh_catch_typeinfo", ty)
+            }
+        };
+        let eh_catch_typeinfo = self.const_bitcast(eh_catch_typeinfo, self.type_i8p());
+        self.eh_catch_typeinfo.set(Some(eh_catch_typeinfo));
+        eh_catch_typeinfo
+    }
 }
 
 impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index bb79a52dcf9..c1dfb83b135 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -855,6 +855,8 @@ fn try_intrinsic(
         bx.store(bx.const_i32(0), dest, ret_align);
     } else if wants_msvc_seh(bx.sess()) {
         codegen_msvc_try(bx, try_func, data, catch_func, dest);
+    } else if bx.sess().target.target.options.is_like_emscripten {
+        codegen_emcc_try(bx, try_func, data, catch_func, dest);
     } else {
         codegen_gnu_try(bx, try_func, data, catch_func, dest);
     }
@@ -880,7 +882,8 @@ fn codegen_msvc_try(
 
         let mut normal = bx.build_sibling_block("normal");
         let mut catchswitch = bx.build_sibling_block("catchswitch");
-        let mut catchpad = bx.build_sibling_block("catchpad");
+        let mut catchpad_rust = bx.build_sibling_block("catchpad_rust");
+        let mut catchpad_foreign = bx.build_sibling_block("catchpad_foreign");
         let mut caught = bx.build_sibling_block("caught");
 
         let try_func = llvm::get_param(bx.llfn(), 0);
@@ -890,21 +893,26 @@ fn codegen_msvc_try(
         // We're generating an IR snippet that looks like:
         //
         //   declare i32 @rust_try(%try_func, %data, %catch_func) {
-        //      %slot = alloca u8*
+        //      %slot = alloca i8*
         //      invoke %try_func(%data) to label %normal unwind label %catchswitch
         //
         //   normal:
         //      ret i32 0
         //
         //   catchswitch:
-        //      %cs = catchswitch within none [%catchpad] unwind to caller
+        //      %cs = catchswitch within none [%catchpad_rust, %catchpad_foreign] unwind to caller
         //
-        //   catchpad:
-        //      %tok = catchpad within %cs [%type_descriptor, 0, %slot]
+        //   catchpad_rust:
+        //      %tok = catchpad within %cs [%type_descriptor, 8, %slot]
         //      %ptr = load %slot
         //      call %catch_func(%data, %ptr)
         //      catchret from %tok to label %caught
         //
+        //   catchpad_foreign:
+        //      %tok = catchpad within %cs [null, 64, null]
+        //      call %catch_func(%data, null)
+        //      catchret from %tok to label %caught
+        //
         //   caught:
         //      ret i32 1
         //   }
@@ -912,13 +920,11 @@ fn codegen_msvc_try(
         // This structure follows the basic usage of throw/try/catch in LLVM.
         // For example, compile this C++ snippet to see what LLVM generates:
         //
-        //      #include <stdint.h>
-        //
         //      struct rust_panic {
         //          rust_panic(const rust_panic&);
         //          ~rust_panic();
         //
-        //          uint64_t x[2];
+        //          void* x[2];
         //      };
         //
         //      int __rust_try(
@@ -932,6 +938,9 @@ fn codegen_msvc_try(
         //          } catch(rust_panic& a) {
         //              catch_func(data, &a);
         //              return 1;
+        //          } catch(...) {
+        //              catch_func(data, NULL);
+        //              return 1;
         //          }
         //      }
         //
@@ -942,8 +951,9 @@ fn codegen_msvc_try(
 
         normal.ret(bx.const_i32(0));
 
-        let cs = catchswitch.catch_switch(None, None, 1);
-        catchswitch.add_handler(cs, catchpad.llbb());
+        let cs = catchswitch.catch_switch(None, None, 2);
+        catchswitch.add_handler(cs, catchpad_rust.llbb());
+        catchswitch.add_handler(cs, catchpad_foreign.llbb());
 
         // We can't use the TypeDescriptor defined in libpanic_unwind because it
         // might be in another DLL and the SEH encoding only supports specifying
@@ -977,11 +987,17 @@ fn codegen_msvc_try(
         //
         // Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang
         let flags = bx.const_i32(8);
-        let funclet = catchpad.catch_pad(cs, &[tydesc, flags, slot]);
-        let ptr = catchpad.load(slot, ptr_align);
-        catchpad.call(catch_func, &[data, ptr], Some(&funclet));
-
-        catchpad.catch_ret(&funclet, caught.llbb());
+        let funclet = catchpad_rust.catch_pad(cs, &[tydesc, flags, slot]);
+        let ptr = catchpad_rust.load(slot, ptr_align);
+        catchpad_rust.call(catch_func, &[data, ptr], Some(&funclet));
+        catchpad_rust.catch_ret(&funclet, caught.llbb());
+
+        // The flag value of 64 indicates a "catch-all".
+        let flags = bx.const_i32(64);
+        let null = bx.const_null(bx.type_i8p());
+        let funclet = catchpad_foreign.catch_pad(cs, &[null, flags, null]);
+        catchpad_foreign.call(catch_func, &[data, null], Some(&funclet));
+        catchpad_foreign.catch_ret(&funclet, caught.llbb());
 
         caught.ret(bx.const_i32(1));
     });
@@ -1044,13 +1060,7 @@ fn codegen_gnu_try(
         // rust_try ignores the selector.
         let lpad_ty = bx.type_struct(&[bx.type_i8p(), bx.type_i32()], false);
         let vals = catch.landing_pad(lpad_ty, bx.eh_personality(), 1);
-        let tydesc = match bx.tcx().lang_items().eh_catch_typeinfo() {
-            Some(tydesc) => {
-                let tydesc = bx.get_static(tydesc);
-                bx.bitcast(tydesc, bx.type_i8p())
-            }
-            None => bx.const_null(bx.type_i8p()),
-        };
+        let tydesc = bx.const_null(bx.type_i8p());
         catch.add_clause(vals, tydesc);
         let ptr = catch.extract_value(vals, 0);
         catch.call(catch_func, &[data, ptr], None);
@@ -1064,6 +1074,88 @@ fn codegen_gnu_try(
     bx.store(ret, dest, i32_align);
 }
 
+// Variant of codegen_gnu_try used for emscripten where Rust panics are
+// implemented using C++ exceptions. Here we use exceptions of a specific type
+// (`struct rust_panic`) to represent Rust panics.
+fn codegen_emcc_try(
+    bx: &mut Builder<'a, 'll, 'tcx>,
+    try_func: &'ll Value,
+    data: &'ll Value,
+    catch_func: &'ll Value,
+    dest: &'ll Value,
+) {
+    let llfn = get_rust_try_fn(bx, &mut |mut bx| {
+        // Codegens the shims described above:
+        //
+        //   bx:
+        //      invoke %try_func(%data) normal %normal unwind %catch
+        //
+        //   normal:
+        //      ret 0
+        //
+        //   catch:
+        //      (%ptr, %selector) = landingpad
+        //      %rust_typeid = @llvm.eh.typeid.for(@_ZTI10rust_panic)
+        //      %is_rust_panic = %selector == %rust_typeid
+        //      %catch_data = alloca { i8*, i8 }
+        //      %catch_data[0] = %ptr
+        //      %catch_data[1] = %is_rust_panic
+        //      call %catch_func(%data, %catch_data)
+        //      ret 1
+
+        bx.sideeffect();
+
+        let mut then = bx.build_sibling_block("then");
+        let mut catch = bx.build_sibling_block("catch");
+
+        let try_func = llvm::get_param(bx.llfn(), 0);
+        let data = llvm::get_param(bx.llfn(), 1);
+        let catch_func = llvm::get_param(bx.llfn(), 2);
+        bx.invoke(try_func, &[data], then.llbb(), catch.llbb(), None);
+        then.ret(bx.const_i32(0));
+
+        // Type indicator for the exception being thrown.
+        //
+        // The first value in this tuple is a pointer to the exception object
+        // being thrown.  The second value is a "selector" indicating which of
+        // the landing pad clauses the exception's type had been matched to.
+        let tydesc = bx.eh_catch_typeinfo();
+        let lpad_ty = bx.type_struct(&[bx.type_i8p(), bx.type_i32()], false);
+        let vals = catch.landing_pad(lpad_ty, bx.eh_personality(), 2);
+        catch.add_clause(vals, tydesc);
+        catch.add_clause(vals, bx.const_null(bx.type_i8p()));
+        let ptr = catch.extract_value(vals, 0);
+        let selector = catch.extract_value(vals, 1);
+
+        // Check if the typeid we got is the one for a Rust panic.
+        let llvm_eh_typeid_for = bx.get_intrinsic("llvm.eh.typeid.for");
+        let rust_typeid = catch.call(llvm_eh_typeid_for, &[tydesc], None);
+        let is_rust_panic = catch.icmp(IntPredicate::IntEQ, selector, rust_typeid);
+        let is_rust_panic = catch.zext(is_rust_panic, bx.type_bool());
+
+        // We need to pass two values to catch_func (ptr and is_rust_panic), so
+        // create an alloca and pass a pointer to that.
+        let ptr_align = bx.tcx().data_layout.pointer_align.abi;
+        let i8_align = bx.tcx().data_layout.i8_align.abi;
+        let catch_data =
+            catch.alloca(bx.type_struct(&[bx.type_i8p(), bx.type_bool()], false), ptr_align);
+        let catch_data_0 = catch.inbounds_gep(catch_data, &[bx.const_usize(0), bx.const_usize(0)]);
+        catch.store(ptr, catch_data_0, ptr_align);
+        let catch_data_1 = catch.inbounds_gep(catch_data, &[bx.const_usize(0), bx.const_usize(1)]);
+        catch.store(is_rust_panic, catch_data_1, i8_align);
+        let catch_data = catch.bitcast(catch_data, bx.type_i8p());
+
+        catch.call(catch_func, &[data, catch_data], None);
+        catch.ret(bx.const_i32(1));
+    });
+
+    // Note that no invoke is used here because by definition this function
+    // can't panic (that's what it's catching).
+    let ret = bx.call(llfn, &[try_func, data, catch_func], None);
+    let i32_align = bx.tcx().data_layout.i32_align.abi;
+    bx.store(ret, dest, i32_align);
+}
+
 // Helper function to give a Block to a closure to codegen a shim function.
 // This is currently primarily used for the `try` intrinsic functions above.
 fn gen_fn<'ll, 'tcx>(
diff --git a/src/librustc_hir/weak_lang_items.rs b/src/librustc_hir/weak_lang_items.rs
index 74e2a90262c..129eec7d29e 100644
--- a/src/librustc_hir/weak_lang_items.rs
+++ b/src/librustc_hir/weak_lang_items.rs
@@ -48,5 +48,6 @@ impl LanguageItems {
 weak_lang_items! {
     panic_impl,         PanicImpl,          rust_begin_unwind;
     eh_personality,     EhPersonality,      rust_eh_personality;
+    eh_catch_typeinfo,  EhCatchTypeinfo,    rust_eh_catch_typeinfo;
     oom,                Oom,                rust_oom;
 }
diff --git a/src/librustc_middle/middle/lang_items.rs b/src/librustc_middle/middle/lang_items.rs
index 3e1caa3b549..7194a035e89 100644
--- a/src/librustc_middle/middle/lang_items.rs
+++ b/src/librustc_middle/middle/lang_items.rs
@@ -53,7 +53,9 @@ pub fn required(tcx: TyCtxt<'_>, lang_item: LangItem) -> bool {
     // symbols. Other panic runtimes ensure that the relevant symbols are
     // available to link things together, but they're never exercised.
     match tcx.sess.panic_strategy() {
-        PanicStrategy::Abort => lang_item != LangItem::EhPersonality,
+        PanicStrategy::Abort => {
+            lang_item != LangItem::EhPersonality && lang_item != LangItem::EhCatchTypeinfo
+        }
         PanicStrategy::Unwind => true,
     }
 }
diff --git a/src/librustc_passes/weak_lang_items.rs b/src/librustc_passes/weak_lang_items.rs
index f559d66587b..6bc2110bfb3 100644
--- a/src/librustc_passes/weak_lang_items.rs
+++ b/src/librustc_passes/weak_lang_items.rs
@@ -26,6 +26,9 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem
     if items.eh_personality().is_none() {
         items.missing.push(LangItem::EhPersonality);
     }
+    if tcx.sess.target.target.options.is_like_emscripten && items.eh_catch_typeinfo().is_none() {
+        items.missing.push(LangItem::EhCatchTypeinfo);
+    }
 
     {
         let mut cx = Context { tcx, items };
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index 46612145bf0..5092b945f72 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -876,6 +876,7 @@ symbols! {
         rust_2015_preview,
         rust_2018_preview,
         rust_begin_unwind,
+        rust_eh_catch_typeinfo,
         rust_eh_personality,
         rust_eh_register_frames,
         rust_eh_unregister_frames,
diff --git a/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs b/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs
index 3e5cdad7ab9..b9ef2f32941 100644
--- a/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs
+++ b/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs
@@ -11,3 +11,5 @@ use core::panic::PanicInfo;
 fn panic_impl(info: &PanicInfo) -> ! { loop {} }
 #[lang = "eh_personality"]
 fn eh_personality() {}
+#[lang = "eh_catch_typeinfo"]
+static EH_CATCH_TYPEINFO: u8 = 0;
diff --git a/src/test/run-make-fulldeps/foreign-exceptions/foo.cpp b/src/test/run-make-fulldeps/foreign-exceptions/foo.cpp
index b0fd65f88e7..8182021a2cc 100644
--- a/src/test/run-make-fulldeps/foreign-exceptions/foo.cpp
+++ b/src/test/run-make-fulldeps/foreign-exceptions/foo.cpp
@@ -23,15 +23,15 @@ struct drop_check {
 extern "C" {
     void rust_catch_callback(void (*cb)(), bool* rust_ok);
 
-    static void callback() {
+    void throw_cxx_exception() {
         println("throwing C++ exception");
         throw exception();
     }
 
-    void throw_cxx_exception() {
+    void test_cxx_exception() {
         bool rust_ok = false;
         try {
-            rust_catch_callback(callback, &rust_ok);
+            rust_catch_callback(throw_cxx_exception, &rust_ok);
             assert(false && "unreachable");
         } catch (exception e) {
             println("caught C++ exception");
diff --git a/src/test/run-make-fulldeps/foreign-exceptions/foo.rs b/src/test/run-make-fulldeps/foreign-exceptions/foo.rs
index 9c2045c8c89..b5c8c1962a8 100644
--- a/src/test/run-make-fulldeps/foreign-exceptions/foo.rs
+++ b/src/test/run-make-fulldeps/foreign-exceptions/foo.rs
@@ -1,5 +1,5 @@
-// Tests that C++ exceptions can unwind through Rust code, run destructors and
-// are ignored by catch_unwind. Also tests that Rust panics can unwind through
+// Tests that C++ exceptions can unwind through Rust code run destructors and
+// are caught by catch_unwind. Also tests that Rust panics can unwind through
 // C++ code.
 
 // For linking libstdc++ on MinGW
@@ -17,7 +17,7 @@ impl<'a> Drop for DropCheck<'a> {
 }
 
 extern "C" {
-    fn throw_cxx_exception();
+    fn test_cxx_exception();
 
     #[unwind(allowed)]
     fn cxx_catch_callback(cb: extern "C" fn(), ok: *mut bool);
@@ -26,15 +26,12 @@ extern "C" {
 #[no_mangle]
 #[unwind(allowed)]
 extern "C" fn rust_catch_callback(cb: extern "C" fn(), rust_ok: &mut bool) {
-    let _caught_unwind = catch_unwind(AssertUnwindSafe(|| {
-        let _drop = DropCheck(rust_ok);
-        cb();
-        unreachable!("should have unwound instead of returned");
-    }));
-    unreachable!("catch_unwind should not have caught foreign exception");
+    let _drop = DropCheck(rust_ok);
+    cb();
+    unreachable!("should have unwound instead of returned");
 }
 
-fn throw_rust_panic() {
+fn test_rust_panic() {
     #[unwind(allowed)]
     extern "C" fn callback() {
         println!("throwing rust panic");
@@ -60,6 +57,6 @@ fn throw_rust_panic() {
 }
 
 fn main() {
-    unsafe { throw_cxx_exception() };
-    throw_rust_panic();
+    unsafe { test_cxx_exception() };
+    test_rust_panic();
 }
diff --git a/src/test/run-make-fulldeps/issue-69368/a.rs b/src/test/run-make-fulldeps/issue-69368/a.rs
index 726db874637..7d339c5a5da 100644
--- a/src/test/run-make-fulldeps/issue-69368/a.rs
+++ b/src/test/run-make-fulldeps/issue-69368/a.rs
@@ -14,3 +14,8 @@ pub fn panic_handler(_: &core::panic::PanicInfo) -> ! {
 extern "C" fn __rust_drop_panic() -> ! {
     loop {}
 }
+
+#[no_mangle]
+extern "C" fn __rust_foreign_exception() -> ! {
+    loop {}
+}
diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
index 6b86feb5921..6b03e847def 100644
--- a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
+++ b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
@@ -17,6 +17,8 @@ const X: () = unimplemented!();
 
 #[lang = "eh_personality"]
 fn eh() {}
+#[lang = "eh_catch_typeinfo"]
+static EH_CATCH_TYPEINFO: u8 = 0;
 
 #[panic_handler]
 fn panic(_info: &PanicInfo) -> ! {
diff --git a/src/test/ui/macros/macro-comma-behavior.core.stderr b/src/test/ui/macros/macro-comma-behavior.core.stderr
index 83a88ab3bd9..dd0cac659fd 100644
--- a/src/test/ui/macros/macro-comma-behavior.core.stderr
+++ b/src/test/ui/macros/macro-comma-behavior.core.stderr
@@ -1,41 +1,41 @@
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:20:23
+  --> $DIR/macro-comma-behavior.rs:21:23
    |
 LL |     assert_eq!(1, 1, "{}",);
    |                       ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:23:23
+  --> $DIR/macro-comma-behavior.rs:24:23
    |
 LL |     assert_ne!(1, 2, "{}",);
    |                       ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:29:29
+  --> $DIR/macro-comma-behavior.rs:30:29
    |
 LL |     debug_assert_eq!(1, 1, "{}",);
    |                             ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:32:29
+  --> $DIR/macro-comma-behavior.rs:33:29
    |
 LL |     debug_assert_ne!(1, 2, "{}",);
    |                             ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:53:19
+  --> $DIR/macro-comma-behavior.rs:54:19
    |
 LL |     format_args!("{}",);
    |                   ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:71:21
+  --> $DIR/macro-comma-behavior.rs:72:21
    |
 LL |     unimplemented!("{}",);
    |                     ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:80:24
+  --> $DIR/macro-comma-behavior.rs:81:24
    |
 LL |             write!(f, "{}",)?;
    |                        ^^
diff --git a/src/test/ui/macros/macro-comma-behavior.rs b/src/test/ui/macros/macro-comma-behavior.rs
index 04714c65b5c..0bfe0683078 100644
--- a/src/test/ui/macros/macro-comma-behavior.rs
+++ b/src/test/ui/macros/macro-comma-behavior.rs
@@ -9,6 +9,7 @@
 #[cfg(std)] use std::fmt;
 #[cfg(core)] use core::fmt;
 #[cfg(core)] #[lang = "eh_personality"] fn eh_personality() {}
+#[cfg(core)] #[lang = "eh_catch_typeinfo"] static EH_CATCH_TYPEINFO: u8 = 0;
 #[cfg(core)] #[lang = "panic_impl"] fn panic_impl(panic: &core::panic::PanicInfo) -> ! { loop {} }
 
 // (see documentation of the similarly-named test in run-pass)
diff --git a/src/test/ui/macros/macro-comma-behavior.std.stderr b/src/test/ui/macros/macro-comma-behavior.std.stderr
index 26445f2c5c5..4372d89fbf5 100644
--- a/src/test/ui/macros/macro-comma-behavior.std.stderr
+++ b/src/test/ui/macros/macro-comma-behavior.std.stderr
@@ -1,59 +1,59 @@
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:20:23
+  --> $DIR/macro-comma-behavior.rs:21:23
    |
 LL |     assert_eq!(1, 1, "{}",);
    |                       ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:23:23
+  --> $DIR/macro-comma-behavior.rs:24:23
    |
 LL |     assert_ne!(1, 2, "{}",);
    |                       ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:29:29
+  --> $DIR/macro-comma-behavior.rs:30:29
    |
 LL |     debug_assert_eq!(1, 1, "{}",);
    |                             ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:32:29
+  --> $DIR/macro-comma-behavior.rs:33:29
    |
 LL |     debug_assert_ne!(1, 2, "{}",);
    |                             ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:37:18
+  --> $DIR/macro-comma-behavior.rs:38:18
    |
 LL |         eprint!("{}",);
    |                  ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:49:18
+  --> $DIR/macro-comma-behavior.rs:50:18
    |
 LL |         format!("{}",);
    |                  ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:53:19
+  --> $DIR/macro-comma-behavior.rs:54:19
    |
 LL |     format_args!("{}",);
    |                   ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:60:17
+  --> $DIR/macro-comma-behavior.rs:61:17
    |
 LL |         print!("{}",);
    |                 ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:71:21
+  --> $DIR/macro-comma-behavior.rs:72:21
    |
 LL |     unimplemented!("{}",);
    |                     ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:80:24
+  --> $DIR/macro-comma-behavior.rs:81:24
    |
 LL |             write!(f, "{}",)?;
    |                        ^^
diff --git a/src/test/ui/no_owned_box_lang_item.rs b/src/test/ui/no_owned_box_lang_item.rs
index 58e45ff73a5..bef630d826c 100644
--- a/src/test/ui/no_owned_box_lang_item.rs
+++ b/src/test/ui/no_owned_box_lang_item.rs
@@ -12,4 +12,5 @@ fn main() {
 }
 
 #[lang = "eh_personality"] extern fn eh_personality() {}
+#[lang = "eh_catch_typeinfo"] static EH_CATCH_TYPEINFO: u8 = 0;
 #[lang = "panic_impl"] fn panic_impl(panic: &PanicInfo) -> ! { loop {} }
diff --git a/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs b/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs
index 3e5cdad7ab9..b9ef2f32941 100644
--- a/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs
+++ b/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs
@@ -11,3 +11,5 @@ use core::panic::PanicInfo;
 fn panic_impl(info: &PanicInfo) -> ! { loop {} }
 #[lang = "eh_personality"]
 fn eh_personality() {}
+#[lang = "eh_catch_typeinfo"]
+static EH_CATCH_TYPEINFO: u8 = 0;
diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs
index c6a3cc346fc..f5d5823e468 100644
--- a/src/test/ui/range/issue-54505-no-std.rs
+++ b/src/test/ui/range/issue-54505-no-std.rs
@@ -14,6 +14,9 @@ use core::ops::RangeBounds;
 #[cfg(any(not(target_arch = "wasm32"), target_os = "emscripten"))]
 #[lang = "eh_personality"]
 extern fn eh_personality() {}
+#[cfg(target_os = "emscripten")]
+#[lang = "eh_catch_typeinfo"]
+static EH_CATCH_TYPEINFO: u8 = 0;
 
 
 // take a reference to any built-in range
diff --git a/src/test/ui/range/issue-54505-no-std.stderr b/src/test/ui/range/issue-54505-no-std.stderr
index 90934061132..5537ed45767 100644
--- a/src/test/ui/range/issue-54505-no-std.stderr
+++ b/src/test/ui/range/issue-54505-no-std.stderr
@@ -1,7 +1,7 @@
 error: `#[panic_handler]` function required, but not found
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:24:16
+  --> $DIR/issue-54505-no-std.rs:27:16
    |
 LL |     take_range(0..1);
    |                ^^^^
@@ -13,7 +13,7 @@ LL |     take_range(0..1);
                  found struct `core::ops::Range<{integer}>`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:29:16
+  --> $DIR/issue-54505-no-std.rs:32:16
    |
 LL |     take_range(1..);
    |                ^^^
@@ -25,7 +25,7 @@ LL |     take_range(1..);
                  found struct `core::ops::RangeFrom<{integer}>`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:34:16
+  --> $DIR/issue-54505-no-std.rs:37:16
    |
 LL |     take_range(..);
    |                ^^
@@ -37,7 +37,7 @@ LL |     take_range(..);
                  found struct `core::ops::RangeFull`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:39:16
+  --> $DIR/issue-54505-no-std.rs:42:16
    |
 LL |     take_range(0..=1);
    |                ^^^^^
@@ -49,7 +49,7 @@ LL |     take_range(0..=1);
                  found struct `core::ops::RangeInclusive<{integer}>`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:44:16
+  --> $DIR/issue-54505-no-std.rs:47:16
    |
 LL |     take_range(..5);
    |                ^^^
@@ -61,7 +61,7 @@ LL |     take_range(..5);
                  found struct `core::ops::RangeTo<{integer}>`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:49:16
+  --> $DIR/issue-54505-no-std.rs:52:16
    |
 LL |     take_range(..=42);
    |                ^^^^^