diff options
| author | Jorge Aparicio <jorge@japaric.io> | 2018-08-19 17:36:04 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2018-09-30 17:26:15 +0200 |
| commit | f9bbb5f31df8232fb1e17a3408b62590c30112c7 (patch) | |
| tree | 9913308c26155b80c1b4decd46c80c39a635daeb /src/librustc_codegen_llvm | |
| parent | 1886d5fe1cdd1a016ecea9fc93d68b3052c528c8 (diff) | |
| download | rust-f9bbb5f31df8232fb1e17a3408b62590c30112c7.tar.gz rust-f9bbb5f31df8232fb1e17a3408b62590c30112c7.zip | |
panic when instantiating an uninhabited type via mem::{uninitialized,zeroed}
Diffstat (limited to 'src/librustc_codegen_llvm')
| -rw-r--r-- | src/librustc_codegen_llvm/mir/block.rs | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index a534b4e478f..72fb9df6f81 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -463,6 +463,55 @@ impl FunctionCx<'a, 'll, 'tcx> { return; } + if (intrinsic == Some("init") || intrinsic == Some("uninit")) && + bx.cx.layout_of(sig.output()).abi.is_uninhabited() + { + let loc = bx.sess().codemap().lookup_char_pos(span.lo()); + let filename = Symbol::intern(&loc.file.name.to_string()).as_str(); + let filename = C_str_slice(bx.cx, filename); + let line = C_u32(bx.cx, loc.line as u32); + let col = C_u32(bx.cx, loc.col.to_usize() as u32 + 1); + let align = tcx.data_layout.aggregate_align + .max(tcx.data_layout.i32_align) + .max(tcx.data_layout.pointer_align); + + let str = if intrinsic == Some("init") { + "Attempted to instantiate an uninhabited type (e.g. `!`) \ + using mem::zeroed()" + } else { + "Attempted to instantiate an uninhabited type (e.g. `!`) \ + using mem::uninitialized()" + }; + let msg_str = Symbol::intern(str).as_str(); + let msg_str = C_str_slice(bx.cx, msg_str); + let msg_file_line_col = C_struct(bx.cx, + &[msg_str, filename, line, col], + false); + let msg_file_line_col = consts::addr_of(bx.cx, + msg_file_line_col, + align, + Some("panic_loc")); + + // Obtain the panic entry point. + let def_id = + common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem); + let instance = ty::Instance::mono(bx.tcx(), def_id); + let fn_ty = FnType::of_instance(bx.cx, &instance); + let llfn = callee::get_fn(bx.cx, instance); + + // Codegen the actual panic invoke/call. + do_call( + self, + bx, + fn_ty, + llfn, + &[msg_file_line_col], + destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)), + cleanup, + ); + return; + } + let extra_args = &args[sig.inputs().len()..]; let extra_args = extra_args.iter().map(|op_arg| { let op_ty = op_arg.ty(self.mir, bx.tcx()); |
