move panic-in-drop=abort
check for drop_in_place
Whether `drop_in_place` can abort does depend on the `panic-in-drop` option while compiling the current crate, not `core`
This commit is contained in:
parent
bd1d18660b
commit
501067cb05
3 changed files with 29 additions and 37 deletions
|
@ -6,6 +6,7 @@ use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
|
|||
use rustc_ast as ast;
|
||||
use rustc_attr as attr;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
|
@ -2762,14 +2763,22 @@ impl<'tcx> ty::Instance<'tcx> {
|
|||
/// with `-Cpanic=abort` will look like they can't unwind when in fact they
|
||||
/// might (from a foreign exception or similar).
|
||||
#[inline]
|
||||
pub fn fn_can_unwind<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
codegen_fn_attr_flags: CodegenFnAttrFlags,
|
||||
abi: SpecAbi,
|
||||
) -> bool {
|
||||
// Special attribute for functions which can't unwind.
|
||||
if codegen_fn_attr_flags.contains(CodegenFnAttrFlags::NEVER_UNWIND) {
|
||||
return false;
|
||||
pub fn fn_can_unwind<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool {
|
||||
if let Some(did) = fn_def_id {
|
||||
// Special attribute for functions which can't unwind.
|
||||
if tcx.codegen_fn_attrs(did).flags.contains(CodegenFnAttrFlags::NEVER_UNWIND) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// With -Z panic-in-drop=abort, drop_in_place never unwinds.
|
||||
//
|
||||
// This is not part of `codegen_fn_attrs` as it can differ between crates
|
||||
// and therefore cannot be computed in core.
|
||||
if tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Abort {
|
||||
if Some(did) == tcx.lang_items().drop_in_place_fn() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise if this isn't special then unwinding is generally determined by
|
||||
|
@ -2991,13 +3000,7 @@ fn fn_abi_of_fn_ptr<'tcx>(
|
|||
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
|
||||
let (param_env, (sig, extra_args)) = query.into_parts();
|
||||
|
||||
LayoutCx { tcx, param_env }.fn_abi_new_uncached(
|
||||
sig,
|
||||
extra_args,
|
||||
None,
|
||||
CodegenFnAttrFlags::empty(),
|
||||
false,
|
||||
)
|
||||
LayoutCx { tcx, param_env }.fn_abi_new_uncached(sig, extra_args, None, None, false)
|
||||
}
|
||||
|
||||
fn fn_abi_of_instance<'tcx>(
|
||||
|
@ -3014,13 +3017,11 @@ fn fn_abi_of_instance<'tcx>(
|
|||
None
|
||||
};
|
||||
|
||||
let attrs = tcx.codegen_fn_attrs(instance.def_id()).flags;
|
||||
|
||||
LayoutCx { tcx, param_env }.fn_abi_new_uncached(
|
||||
sig,
|
||||
extra_args,
|
||||
caller_location,
|
||||
attrs,
|
||||
Some(instance.def_id()),
|
||||
matches!(instance.def, ty::InstanceDef::Virtual(..)),
|
||||
)
|
||||
}
|
||||
|
@ -3033,7 +3034,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||
sig: ty::PolyFnSig<'tcx>,
|
||||
extra_args: &[Ty<'tcx>],
|
||||
caller_location: Option<Ty<'tcx>>,
|
||||
codegen_fn_attr_flags: CodegenFnAttrFlags,
|
||||
fn_def_id: Option<DefId>,
|
||||
// FIXME(eddyb) replace this with something typed, like an `enum`.
|
||||
force_thin_self_ptr: bool,
|
||||
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
|
||||
|
@ -3205,7 +3206,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||
c_variadic: sig.c_variadic,
|
||||
fixed_count: inputs.len(),
|
||||
conv,
|
||||
can_unwind: fn_can_unwind(self.tcx(), codegen_fn_attr_flags, sig.abi),
|
||||
can_unwind: fn_can_unwind(self.tcx(), fn_def_id, sig.abi),
|
||||
};
|
||||
self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?;
|
||||
debug!("fn_abi_new_uncached = {:?}", fn_abi);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::MirPass;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::layout;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
|
@ -46,7 +45,6 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
|
|||
//
|
||||
// Here we test for this function itself whether its ABI allows
|
||||
// unwinding or not.
|
||||
let body_flags = tcx.codegen_fn_attrs(def_id).flags;
|
||||
let body_ty = tcx.type_of(def_id);
|
||||
let body_abi = match body_ty.kind() {
|
||||
ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
|
||||
|
@ -54,7 +52,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
|
|||
ty::Generator(..) => Abi::Rust,
|
||||
_ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty),
|
||||
};
|
||||
let body_can_unwind = layout::fn_can_unwind(tcx, body_flags, body_abi);
|
||||
let body_can_unwind = layout::fn_can_unwind(tcx, Some(def_id), body_abi);
|
||||
|
||||
// Look in this function body for any basic blocks which are terminated
|
||||
// with a function call, and whose function we're calling may unwind.
|
||||
|
@ -73,19 +71,19 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
|
|||
TerminatorKind::Call { func, .. } => {
|
||||
let ty = func.ty(body, tcx);
|
||||
let sig = ty.fn_sig(tcx);
|
||||
let flags = match ty.kind() {
|
||||
ty::FnPtr(_) => CodegenFnAttrFlags::empty(),
|
||||
ty::FnDef(def_id, _) => tcx.codegen_fn_attrs(*def_id).flags,
|
||||
let fn_def_id = match ty.kind() {
|
||||
ty::FnPtr(_) => None,
|
||||
&ty::FnDef(def_id, _) => Some(def_id),
|
||||
_ => span_bug!(span, "invalid callee of type {:?}", ty),
|
||||
};
|
||||
layout::fn_can_unwind(tcx, flags, sig.abi())
|
||||
layout::fn_can_unwind(tcx, fn_def_id, sig.abi())
|
||||
}
|
||||
TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => {
|
||||
tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Unwind
|
||||
&& layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust)
|
||||
&& layout::fn_can_unwind(tcx, None, Abi::Rust)
|
||||
}
|
||||
TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } => {
|
||||
layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust)
|
||||
layout::fn_can_unwind(tcx, None, Abi::Rust)
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
|
|
|
@ -45,7 +45,7 @@ use rustc_session::lint;
|
|||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::spec::{abi, PanicStrategy, SanitizerSet};
|
||||
use rustc_target::spec::{abi, SanitizerSet};
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
|
||||
use std::iter;
|
||||
|
||||
|
@ -2726,13 +2726,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
|
|||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
|
||||
}
|
||||
|
||||
// With -Z panic-in-drop=abort, drop_in_place never unwinds.
|
||||
if tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Abort {
|
||||
if Some(did.to_def_id()) == tcx.lang_items().drop_in_place_fn() {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
|
||||
}
|
||||
}
|
||||
|
||||
// The panic_no_unwind function called by TerminatorKind::Abort will never
|
||||
// unwind. If the panic handler that it invokes unwind then it will simply
|
||||
// call the panic handler again.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue