Skip to content

Commit 96a8048

Browse files
committed
rustc_ast_passes: allow c-variadic associated fns
- Allow c-variadic associated functions - Add test for c-variadic functions in the Impl context
1 parent 953f33c commit 96a8048

File tree

3 files changed

+73
-1
lines changed

3 files changed

+73
-1
lines changed

compiler/rustc_ast_passes/src/ast_validation.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,8 @@ impl<'a> AstValidator<'a> {
537537
fn check_c_varadic_type(&self, fk: FnKind<'a>) {
538538
match (fk.ctxt(), fk.header()) {
539539
(Some(FnCtxt::Foreign), _) => return,
540-
(Some(FnCtxt::Free), Some(header)) => match header.ext {
540+
(Some(FnCtxt::Free), Some(header))
541+
| (Some(FnCtxt::Assoc(AssocCtxt::Impl)), Some(header)) => match header.ext {
541542
Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }) | Extern::Implicit
542543
if matches!(header.unsafety, Unsafe::Yes(_)) =>
543544
{

src/test/ui/c-variadic/variadic-ffi-6.rs

+16
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,19 @@ pub unsafe extern "C" fn use_vararg_lifetime(
1111
pub unsafe extern "C" fn use_normal_arg_lifetime(x: &usize, y: ...) -> &usize { // OK
1212
x
1313
}
14+
15+
#[repr(C)]
16+
pub struct Foo(usize);
17+
18+
19+
impl Foo {
20+
#[no_mangle]
21+
pub unsafe extern "C" fn assoc_fn(_format: *const i8, ap: ...) -> usize { // OK
22+
ap.arg()
23+
}
24+
25+
#[no_mangle]
26+
pub unsafe extern "C" fn method(&self, _format: *const i8, ap: ...) -> usize { // OK
27+
ap.arg()
28+
}
29+
}
+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// run-pass
2+
#![feature(c_variadic)]
3+
4+
macro_rules! variadic_tests {
5+
(generate) => {
6+
pub unsafe extern "C" fn sum(n: usize, mut ap: ...) -> usize {
7+
(0..n).fold(0usize, |acc, _| {
8+
acc + ap.arg::<usize>()
9+
})
10+
}
11+
12+
pub unsafe extern "C" fn mixed_types(_: usize, mut ap: ...) {
13+
use std::ffi::{CString, CStr};
14+
15+
assert_eq!(ap.arg::<f64>().floor(), 12.0f64.floor());
16+
assert_eq!(ap.arg::<u32>(), 0x10000001);
17+
assert_eq!(ap.arg::<i8>(), 0x42);
18+
let cstr = CStr::from_ptr(ap.arg::<*const i8>());
19+
assert!(cstr == &*CString::new("Hello").unwrap());
20+
}
21+
};
22+
23+
(test_sum $p:path) => {
24+
unsafe {
25+
assert_eq!($p(5, 2, 4, 8, 16, 32), 62);
26+
assert_eq!($p(4, 10, 8, 8, 16, 2), 42);
27+
}
28+
};
29+
30+
(test_mixed_types $p:path) => {
31+
unsafe {
32+
use std::ffi::CString;
33+
34+
$p(0, 12.56f64, 0x10000001, 0x42, CString::new("Hello").unwrap().as_ptr());
35+
}
36+
}
37+
}
38+
39+
mod foo {
40+
variadic_tests!(generate);
41+
}
42+
43+
struct Foo;
44+
45+
impl Foo {
46+
variadic_tests!(generate);
47+
}
48+
49+
fn main() {
50+
variadic_tests!(test_sum foo::sum);
51+
variadic_tests!(test_sum Foo::sum);
52+
53+
variadic_tests!(test_mixed_types foo::mixed_types);
54+
variadic_tests!(test_mixed_types Foo::mixed_types);
55+
}

0 commit comments

Comments
 (0)