Skip to content

Commit fbe0075

Browse files
committed
Don't infer unwinding of virtual calls based on the function attributes
1 parent 8089fce commit fbe0075

File tree

2 files changed

+32
-6
lines changed

2 files changed

+32
-6
lines changed

Diff for: compiler/rustc_ty_utils/src/abi.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -543,11 +543,13 @@ fn fn_abi_new_uncached<'tcx>(
543543
instance: Option<ty::Instance<'tcx>>,
544544
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
545545
let tcx = cx.tcx();
546-
let (caller_location, fn_def_id, is_virtual_call) = if let Some(instance) = instance {
546+
let (caller_location, determined_fn_def_id, is_virtual_call) = if let Some(instance) = instance
547+
{
548+
let is_virtual_call = matches!(instance.def, ty::InstanceKind::Virtual(..));
547549
(
548550
instance.def.requires_caller_location(tcx).then(|| tcx.caller_location_ty()),
549-
Some(instance.def_id()),
550-
matches!(instance.def, ty::InstanceKind::Virtual(..)),
551+
if is_virtual_call { None } else { Some(instance.def_id()) },
552+
is_virtual_call,
551553
)
552554
} else {
553555
(None, None, false)
@@ -577,7 +579,7 @@ fn fn_abi_new_uncached<'tcx>(
577579
};
578580

579581
let is_drop_in_place =
580-
fn_def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::DropInPlace));
582+
determined_fn_def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::DropInPlace));
581583

582584
let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, &'tcx FnAbiError<'tcx>> {
583585
let span = tracing::debug_span!("arg_of");
@@ -633,7 +635,12 @@ fn fn_abi_new_uncached<'tcx>(
633635
c_variadic: sig.c_variadic,
634636
fixed_count: inputs.len() as u32,
635637
conv,
636-
can_unwind: fn_can_unwind(cx.tcx(), fn_def_id, sig.abi),
638+
can_unwind: fn_can_unwind(
639+
tcx,
640+
// Since `#[rustc_nounwind]` can change unwinding, we cannot infer unwinding by `fn_def_id` for a virtual call.
641+
determined_fn_def_id,
642+
sig.abi,
643+
),
637644
};
638645
fn_abi_adjust_for_abi(
639646
cx,
@@ -642,7 +649,7 @@ fn fn_abi_new_uncached<'tcx>(
642649
// If this is a virtual call, we cannot pass the `fn_def_id`, as it might call other
643650
// functions from vtable. Internally, `deduced_param_attrs` attempts to infer attributes by
644651
// visit the function body.
645-
fn_def_id.filter(|_| !is_virtual_call),
652+
determined_fn_def_id,
646653
);
647654
debug!("fn_abi_new_uncached = {:?}", fn_abi);
648655
fn_abi_sanity_check(cx, &fn_abi, sig.abi);

Diff for: tests/codegen/virtual-call-attrs-issue-137646.rs

+19
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
//@ compile-flags: -C opt-level=3 -C no-prepopulate-passes
55

66
#![crate_type = "lib"]
7+
#![feature(rustc_attrs)]
78

89
pub trait Trait {
10+
#[rustc_nounwind]
911
fn m(&self, _: (i32, i32, i32)) {}
1012
}
1113

@@ -16,3 +18,20 @@ pub fn foo(trait_: &dyn Trait) {
1618
// CHECK-NOT: readonly
1719
trait_.m((1, 1, 1));
1820
}
21+
22+
#[no_mangle]
23+
#[rustc_nounwind]
24+
pub fn foo_nounwind(trait_: &dyn Trait) {
25+
// CHECK-LABEL: @foo_nounwind(
26+
// FIXME: Here should be invoke.
27+
// COM: CHECK: invoke
28+
trait_.m((1, 1, 1));
29+
}
30+
31+
#[no_mangle]
32+
pub extern "C" fn c_nounwind(trait_: &dyn Trait) {
33+
// CHECK-LABEL: @c_nounwind(
34+
// FIXME: Here should be invoke.
35+
// COM: CHECK: invoke
36+
trait_.m((1, 1, 1));
37+
}

0 commit comments

Comments
 (0)