Skip to content

Commit 8d4c615

Browse files
committed
Add "C++-unwind" support
1 parent 07d2bca commit 8d4c615

File tree

5 files changed

+27
-11
lines changed

5 files changed

+27
-11
lines changed

gen/src/write.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use crate::syntax::set::UnorderedSet;
1010
use crate::syntax::symbol::{self, Symbol};
1111
use crate::syntax::trivial::{self, TrivialReason};
1212
use crate::syntax::{
13-
derive, mangle, Api, Doc, Enum, EnumRepr, ExternFn, ExternType, Pair, Signature, Struct, Trait,
14-
Type, TypeAlias, Types, Var,
13+
derive, mangle, Api, Doc, Enum, EnumRepr, ExternFn, ExternType, Lang, Pair, Signature, Struct,
14+
Trait, Type, TypeAlias, Types, Var,
1515
};
1616
use proc_macro2::Ident;
1717

@@ -779,7 +779,11 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
779779
write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
780780
write!(out, "*return$");
781781
}
782-
writeln!(out, ") noexcept {{");
782+
if efn.lang == Lang::CxxUnwind {
783+
writeln!(out, ") {{");
784+
} else {
785+
writeln!(out, ") noexcept {{");
786+
}
783787
write!(out, " ");
784788
write_return_type(out, &efn.ret);
785789
match &efn.receiver {

macro/src/expand.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -733,8 +733,13 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
733733
let ident = &efn.name.rust;
734734
let generics = &efn.generics;
735735
let arg_list = quote_spanned!(efn.paren_token.span=> (#(#all_args,)*));
736+
let calling_conv = if let syntax::Lang::CxxUnwind = efn.lang {
737+
quote_spanned!(span => extern "C-unwind")
738+
} else {
739+
quote_spanned!(span => extern "C")
740+
};
736741
let fn_body = quote_spanned!(span=> {
737-
#UnsafeExtern extern "C" {
742+
#UnsafeExtern #calling_conv {
738743
#decl
739744
}
740745
#trampolines
@@ -806,11 +811,16 @@ fn expand_function_pointer_trampoline(
806811
body_span,
807812
);
808813
let var = &var.rust;
814+
let calling_conv = if let syntax::Lang::CxxUnwind = efn.lang {
815+
quote!(extern "C-unwind")
816+
} else {
817+
quote!(extern "C")
818+
};
809819

810820
quote! {
811821
let #var = ::cxx::private::FatFunction {
812822
trampoline: {
813-
#UnsafeExtern extern "C" {
823+
#UnsafeExtern #calling_conv {
814824
#[link_name = #c_trampoline]
815825
fn trampoline();
816826
}

syntax/check.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
383383
}
384384
let lang = match ety.lang {
385385
Lang::Rust => "Rust",
386-
Lang::Cxx => "C++",
386+
Lang::Cxx | Lang::CxxUnwind => "C++",
387387
};
388388
let msg = format!(
389389
"derive({}) on opaque {} type is not supported yet",
@@ -409,7 +409,7 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
409409

410410
fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
411411
match efn.lang {
412-
Lang::Cxx => {
412+
Lang::Cxx | Lang::CxxUnwind => {
413413
if !efn.generics.params.is_empty() && !efn.trusted {
414414
let ref span = span_for_generics_error(efn);
415415
cx.error(span, "extern C++ function with lifetimes must be declared in `unsafe extern \"C++\"` block");

syntax/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ pub(crate) struct Array {
323323
#[derive(Copy, Clone, PartialEq)]
324324
pub(crate) enum Lang {
325325
Cxx,
326+
CxxUnwind,
326327
Rust,
327328
}
328329

syntax/parse.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ fn parse_foreign_mod(
353353
cx.error(span, "extern \"Rust\" block does not need to be unsafe");
354354
}
355355
}
356-
Lang::Cxx => {}
356+
Lang::Cxx | Lang::CxxUnwind => {}
357357
}
358358

359359
let trusted = trusted || foreign_mod.unsafety.is_some();
@@ -445,6 +445,7 @@ fn parse_lang(abi: &Abi) -> Result<Lang> {
445445

446446
match name.value().as_str() {
447447
"C++" => Ok(Lang::Cxx),
448+
"C++-unwind" => Ok(Lang::CxxUnwind),
448449
"Rust" => Ok(Lang::Rust),
449450
_ => Err(Error::new_spanned(
450451
abi,
@@ -492,7 +493,7 @@ fn parse_extern_type(
492493
let semi_token = foreign_type.semi_token;
493494

494495
(match lang {
495-
Lang::Cxx => Api::CxxType,
496+
Lang::Cxx | Lang::CxxUnwind => Api::CxxType,
496497
Lang::Rust => Api::RustType,
497498
})(ExternType {
498499
cfg,
@@ -671,7 +672,7 @@ fn parse_extern_fn(
671672
let semi_token = foreign_fn.semi_token;
672673

673674
Ok(match lang {
674-
Lang::Cxx => Api::CxxFunction,
675+
Lang::Cxx | Lang::CxxUnwind => Api::CxxFunction,
675676
Lang::Rust => Api::RustFunction,
676677
}(ExternFn {
677678
cfg,
@@ -964,7 +965,7 @@ fn parse_extern_type_bounded(
964965
let name = pair(namespace, &ident, cxx_name, rust_name);
965966

966967
Ok(match lang {
967-
Lang::Cxx => Api::CxxType,
968+
Lang::Cxx | Lang::CxxUnwind => Api::CxxType,
968969
Lang::Rust => Api::RustType,
969970
}(ExternType {
970971
cfg,

0 commit comments

Comments
 (0)