2019-07-26 21:54:25 +00:00
|
|
|
//@ run-pass
|
2014-05-12 01:56:53 +00:00
|
|
|
// #11303, #11040:
|
2014-09-02 05:35:58 +00:00
|
|
|
// This would previously crash on i686 Linux due to abi differences
|
2014-05-12 01:56:53 +00:00
|
|
|
// between returning an Option<T> and T, where T is a non nullable
|
|
|
|
// pointer.
|
|
|
|
// If we have an enum with two variants such that one is zero sized
|
|
|
|
// and the other contains a nonnullable pointer, we don't use a
|
|
|
|
// separate discriminant. Instead we use that pointer field to differentiate
|
|
|
|
// between the 2 cases.
|
|
|
|
// Also, if the variant with the nonnullable pointer has no other fields
|
|
|
|
// then we simply express the enum as just a pointer and not wrap it
|
|
|
|
// in a struct.
|
|
|
|
|
2015-03-22 20:13:15 +00:00
|
|
|
|
2014-05-12 01:56:53 +00:00
|
|
|
use std::mem;
|
|
|
|
|
|
|
|
#[inline(never)]
|
2016-02-18 13:19:38 +00:00
|
|
|
extern "C" fn foo(x: &isize) -> Option<&isize> { Some(x) }
|
2014-05-12 01:56:53 +00:00
|
|
|
|
2015-03-26 00:06:52 +00:00
|
|
|
static FOO: isize = 0xDEADBEE;
|
2014-05-12 01:56:53 +00:00
|
|
|
|
|
|
|
pub fn main() {
|
|
|
|
unsafe {
|
2016-02-18 13:19:38 +00:00
|
|
|
let f: extern "C" fn(&isize) -> &isize =
|
|
|
|
mem::transmute(foo as extern "C" fn(&isize) -> Option<&isize>);
|
2014-05-12 01:56:53 +00:00
|
|
|
assert_eq!(*f(&FOO), FOO);
|
|
|
|
}
|
|
|
|
}
|