]> git.lizzy.rs Git - rust.git/commitdiff
Add tests for variadic foreign functions.
authorLuqman Aden <laden@csclub.uwaterloo.ca>
Mon, 4 Nov 2013 21:34:07 +0000 (16:34 -0500)
committerLuqman Aden <laden@csclub.uwaterloo.ca>
Tue, 5 Nov 2013 04:53:11 +0000 (23:53 -0500)
src/test/compile-fail/variadic-ffi-1.rs [new file with mode: 0644]
src/test/compile-fail/variadic-ffi-2.rs [new file with mode: 0644]
src/test/compile-fail/variadic-ffi-3.rs [new file with mode: 0644]
src/test/compile-fail/variadic-ffi-4.rs [new file with mode: 0644]
src/test/compile-fail/variadic-ffi.rs [new file with mode: 0644]
src/test/run-pass/variadic-ffi.rs [new file with mode: 0644]

diff --git a/src/test/compile-fail/variadic-ffi-1.rs b/src/test/compile-fail/variadic-ffi-1.rs
new file mode 100644 (file)
index 0000000..93f702d
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern {
+    fn printf(...); //~ ERROR: variadic function must be declared with at least one named argument
+    fn printf(..., foo: int); //~ ERROR: `...` must be last in argument list for variadic function
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/variadic-ffi-2.rs b/src/test/compile-fail/variadic-ffi-2.rs
new file mode 100644 (file)
index 0000000..9e2b015
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn baz(f: extern "stdcall" fn(uint, ...)) {
+    //~^ ERROR: variadic function must have C calling convention
+    f(22, 44);
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/variadic-ffi-3.rs b/src/test/compile-fail/variadic-ffi-3.rs
new file mode 100644 (file)
index 0000000..f143e71
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo(x: int, ...) {
+    //~^ ERROR: only foreign functions are allowed to be variadic
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/variadic-ffi-4.rs b/src/test/compile-fail/variadic-ffi-4.rs
new file mode 100644 (file)
index 0000000..d4c54df
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern "C" fn foo(x: int, ...) {
+    //~^ ERROR: only foreign functions are allowed to be variadic
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/variadic-ffi.rs b/src/test/compile-fail/variadic-ffi.rs
new file mode 100644 (file)
index 0000000..4133f00
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern "stdcall" {
+    fn printf(_: *u8, ...); //~ ERROR: variadic function must have C calling convention
+}
+
+extern {
+    fn foo(f: int, x: u8, ...);
+}
+
+extern "C" fn bar(f: int, x: u8) {}
+
+#[fixed_stack_segment]
+fn main() {
+    unsafe {
+        foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied
+        foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied
+
+        let x: extern "C" unsafe fn(f: int, x: u8) = foo;
+        //~^ ERROR: mismatched types: expected `extern "C" unsafe fn(int, u8)` but found `extern "C" unsafe fn(int, u8, ...)` (expected non-variadic fn but found variadic function)
+
+        let y: extern "C" unsafe fn(f: int, x: u8, ...) = bar;
+        //~^ ERROR: mismatched types: expected `extern "C" unsafe fn(int, u8, ...)` but found `extern "C" extern fn(int, u8)` (expected variadic fn but found non-variadic function)
+
+        foo(1, 2, 3f32); //~ ERROR: can't pass an f32 to variadic function, cast to c_double
+        foo(1, 2, true); //~ ERROR: can't pass bool to variadic function, cast to c_int
+        foo(1, 2, 1i8); //~ ERROR: can't pass i8 to variadic function, cast to c_int
+        foo(1, 2, 1u8); //~ ERROR: can't pass u8 to variadic function, cast to c_uint
+        foo(1, 2, 1i16); //~ ERROR: can't pass i16 to variadic function, cast to c_int
+        foo(1, 2, 1u16); //~ ERROR: can't pass u16 to variadic function, cast to c_uint
+    }
+}
diff --git a/src/test/run-pass/variadic-ffi.rs b/src/test/run-pass/variadic-ffi.rs
new file mode 100644 (file)
index 0000000..6f8867a
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::c_str::CString;
+use std::libc::{c_char, c_int};
+
+extern {
+    fn sprintf(s: *mut c_char, format: *c_char, ...) -> c_int;
+}
+
+unsafe fn check<T>(expected: &str, f: &fn(*mut c_char) -> T) {
+    let mut x = [0i8, ..50];
+    f(&mut x[0] as *mut c_char);
+    let res = CString::new(&x[0], false);
+    assert_eq!(expected, res.as_str().unwrap());
+}
+
+#[fixed_stack_segment]
+pub fn main() {
+
+    unsafe {
+        // Call with just the named parameter
+        do "Hello World\n".with_c_str |c| {
+            check("Hello World\n", |s| sprintf(s, c));
+        }
+
+        // Call with variable number of arguments
+        do "%d %f %c %s\n".with_c_str |c| {
+            do check("42 42.500000 a %d %f %c %s\n\n") |s| {
+                sprintf(s, c, 42i, 42.5f64, 'a' as c_int, c);
+            }
+        }
+
+        // Make a function pointer
+        let x: extern "C" unsafe fn(*mut c_char, *c_char, ...) -> c_int = sprintf;
+
+        // A function that takes a function pointer
+        unsafe fn call(p: extern "C" unsafe fn(*mut c_char, *c_char, ...) -> c_int) {
+            #[fixed_stack_segment];
+
+            // Call with just the named parameter via fn pointer
+            do "Hello World\n".with_c_str |c| {
+                check("Hello World\n", |s| p(s, c));
+            }
+
+            // Call with variable number of arguments
+            do "%d %f %c %s\n".with_c_str |c| {
+                do check("42 42.500000 a %d %f %c %s\n\n") |s| {
+                    p(s, c, 42i, 42.5f64, 'a' as c_int, c);
+                }
+            }
+        }
+
+        // Pass sprintf directly
+        call(sprintf);
+
+        // Pass sprintf indirectly
+        call(x);
+    }
+
+}