From 96a8048f46a943fe034826df80f54d4b06276117 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Fri, 18 Sep 2020 13:08:31 +0000 Subject: [PATCH] rustc_ast_passes: allow c-variadic associated fns - Allow c-variadic associated functions - Add test for c-variadic functions in the Impl context --- .../rustc_ast_passes/src/ast_validation.rs | 3 +- src/test/ui/c-variadic/variadic-ffi-6.rs | 16 ++++++ src/test/ui/c-variadic/variadic-ffi-7.rs | 55 +++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/c-variadic/variadic-ffi-7.rs diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 31c05325d1d25..2aae1e45d8c51 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -537,7 +537,8 @@ impl<'a> AstValidator<'a> { fn check_c_varadic_type(&self, fk: FnKind<'a>) { match (fk.ctxt(), fk.header()) { (Some(FnCtxt::Foreign), _) => return, - (Some(FnCtxt::Free), Some(header)) => match header.ext { + (Some(FnCtxt::Free), Some(header)) + | (Some(FnCtxt::Assoc(AssocCtxt::Impl)), Some(header)) => match header.ext { Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }) | Extern::Implicit if matches!(header.unsafety, Unsafe::Yes(_)) => { diff --git a/src/test/ui/c-variadic/variadic-ffi-6.rs b/src/test/ui/c-variadic/variadic-ffi-6.rs index 4dd8a2d452181..644c4cf3f6d17 100644 --- a/src/test/ui/c-variadic/variadic-ffi-6.rs +++ b/src/test/ui/c-variadic/variadic-ffi-6.rs @@ -11,3 +11,19 @@ pub unsafe extern "C" fn use_vararg_lifetime( pub unsafe extern "C" fn use_normal_arg_lifetime(x: &usize, y: ...) -> &usize { // OK x } + +#[repr(C)] +pub struct Foo(usize); + + +impl Foo { + #[no_mangle] + pub unsafe extern "C" fn assoc_fn(_format: *const i8, ap: ...) -> usize { // OK + ap.arg() + } + + #[no_mangle] + pub unsafe extern "C" fn method(&self, _format: *const i8, ap: ...) -> usize { // OK + ap.arg() + } +} diff --git a/src/test/ui/c-variadic/variadic-ffi-7.rs b/src/test/ui/c-variadic/variadic-ffi-7.rs new file mode 100644 index 0000000000000..8c1d592e7eb26 --- /dev/null +++ b/src/test/ui/c-variadic/variadic-ffi-7.rs @@ -0,0 +1,55 @@ +// run-pass +#![feature(c_variadic)] + +macro_rules! variadic_tests { + (generate) => { + pub unsafe extern "C" fn sum(n: usize, mut ap: ...) -> usize { + (0..n).fold(0usize, |acc, _| { + acc + ap.arg::() + }) + } + + pub unsafe extern "C" fn mixed_types(_: usize, mut ap: ...) { + use std::ffi::{CString, CStr}; + + assert_eq!(ap.arg::().floor(), 12.0f64.floor()); + assert_eq!(ap.arg::(), 0x10000001); + assert_eq!(ap.arg::(), 0x42); + let cstr = CStr::from_ptr(ap.arg::<*const i8>()); + assert!(cstr == &*CString::new("Hello").unwrap()); + } + }; + + (test_sum $p:path) => { + unsafe { + assert_eq!($p(5, 2, 4, 8, 16, 32), 62); + assert_eq!($p(4, 10, 8, 8, 16, 2), 42); + } + }; + + (test_mixed_types $p:path) => { + unsafe { + use std::ffi::CString; + + $p(0, 12.56f64, 0x10000001, 0x42, CString::new("Hello").unwrap().as_ptr()); + } + } +} + +mod foo { + variadic_tests!(generate); +} + +struct Foo; + +impl Foo { + variadic_tests!(generate); +} + +fn main() { + variadic_tests!(test_sum foo::sum); + variadic_tests!(test_sum Foo::sum); + + variadic_tests!(test_mixed_types foo::mixed_types); + variadic_tests!(test_mixed_types Foo::mixed_types); +}