Skip to content

Commit

Permalink
rustc_ast_passes: allow c-variadic associated fns
Browse files Browse the repository at this point in the history
 - Allow c-variadic associated functions
 - Add test for c-variadic functions in the Impl context
  • Loading branch information
dlrobertson committed Sep 18, 2020
1 parent 953f33c commit 96a8048
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 1 deletion.
3 changes: 2 additions & 1 deletion compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(_)) =>
{
Expand Down
16 changes: 16 additions & 0 deletions src/test/ui/c-variadic/variadic-ffi-6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
55 changes: 55 additions & 0 deletions src/test/ui/c-variadic/variadic-ffi-7.rs
Original file line number Diff line number Diff line change
@@ -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::<usize>()
})
}

pub unsafe extern "C" fn mixed_types(_: usize, mut ap: ...) {
use std::ffi::{CString, CStr};

assert_eq!(ap.arg::<f64>().floor(), 12.0f64.floor());
assert_eq!(ap.arg::<u32>(), 0x10000001);
assert_eq!(ap.arg::<i8>(), 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);
}

0 comments on commit 96a8048

Please sign in to comment.