auto merge of #16499 : cmr/rust/struct-undef-repr, r=pcwalton

r? @pcwalton
This commit is contained in:
bors 2014-08-21 17:30:57 +00:00
commit f92015f71b
45 changed files with 505 additions and 219 deletions

View File

@ -263,12 +263,13 @@ Rust code:
~~~~no_run
#[repr(C)]
struct RustObject {
a: i32,
// other members
}
extern fn callback(target: *mut RustObject, a:i32) {
extern "C" fn callback(target: *mut RustObject, a:i32) {
println!("I'm called from C with value {0}", a);
unsafe {
// Update the value in RustObject with the value received from the callback
@ -506,16 +507,16 @@ to define a block for all windows systems, not just x86 ones.
# Interoperability with foreign code
Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C.
A `#[packed]` attribute is available, which will lay out the struct members without padding.
However, there are currently no guarantees about the layout of an `enum`.
Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C
only if the `#[repr(C)]` attribute is applied to it. `#[repr(C, packed)]` can be used to lay out
struct members without padding. `#[repr(C)]` can also be applied to an enum.
Rust's owned and managed boxes use non-nullable pointers as handles which point to the contained
Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point to the contained
object. However, they should not be manually created because they are managed by internal
allocators. References can safely be assumed to be non-nullable pointers directly to the
type. However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so
prefer using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions
about them.
allocators. References can safely be assumed to be non-nullable pointers directly to the type.
However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so prefer
using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions about
them.
Vectors and strings share the same basic memory layout, and utilities are available in the `vec` and
`str` modules for working with C APIs. However, strings are not terminated with `\0`. If you need a

View File

@ -1308,6 +1308,9 @@ struct Cookie;
let c = [Cookie, Cookie, Cookie, Cookie];
~~~~
The precise memory layout of a structure is not specified. One can specify a
particular layout using the [`repr` attribute](#ffi-attributes).
By using the `struct_inherit` feature gate, structures may use single inheritance. A Structure may only
inherit from a single other structure, called the _super-struct_. The inheriting structure (sub-struct)
acts as if all fields in the super-struct were present in the sub-struct. Fields declared in a sub-struct
@ -1941,6 +1944,23 @@ interpreted:
- `linkage` - on a static, this specifies the [linkage
type](http://llvm.org/docs/LangRef.html#linkage-types).
On `enum`s:
- `repr` - on C-like enums, this sets the underlying type used for
representation. Takes one argument, which is the primitive
type this enum should be represented for, or `C`, which specifies that it
should be the default `enum` size of the C ABI for that platform. Note that
enum representation in C is undefined, and this may be incorrect when the C
code is compiled with certain flags.
On `struct`s:
- `repr` - specifies the representation to use for this struct. Takes a list
of options. The currently accepted ones are `C` and `packed`, which may be
combined. `C` will use a C ABI comptible struct layout, and `packed` will
remove any padding between fields (note that this is very fragile and may
break platforms which require aligned access).
### Miscellaneous attributes
- `export_name` - on statics and functions, this determines the name of the
@ -1958,12 +1978,6 @@ interpreted:
crate at compile-time and use any syntax extensions or lints that the crate
defines. They can both be specified, `#[phase(link, plugin)]` to use a crate
both at runtime and compiletime.
- `repr` - on C-like enums, this sets the underlying type used for
representation. Useful for FFI. Takes one argument, which is the primitive
type this enum should be represented for, or `C`, which specifies that it
should be the default `enum` size of the C ABI for that platform. Note that
enum representation in C is undefined, and this may be incorrect when the C
code is compiled with certain flags.
- `simd` - on certain tuple structs, derive the arithmetic operators, which
lower to the target's SIMD instructions, if any; the `simd` feature gate
is necessary to use this attribute.

View File

@ -40,6 +40,7 @@
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
pub i8, pub i8, pub i8, pub i8,
pub i8, pub i8, pub i8, pub i8,
@ -48,22 +49,26 @@ pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct i16x8(pub i16, pub i16, pub i16, pub i16,
pub i16, pub i16, pub i16, pub i16);
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct i32x4(pub i32, pub i32, pub i32, pub i32);
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct i64x2(pub i64, pub i64);
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
pub u8, pub u8, pub u8, pub u8,
pub u8, pub u8, pub u8, pub u8,
@ -72,25 +77,30 @@ pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct u16x8(pub u16, pub u16, pub u16, pub u16,
pub u16, pub u16, pub u16, pub u16);
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct u64x2(pub u64, pub u64);
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct f64x2(pub f64, pub f64);

View File

@ -15,6 +15,7 @@ use std::rt::stack;
use std::raw;
#[cfg(target_arch = "x86_64")]
use std::simd;
use libc;
// FIXME #7761: Registers is boxed so that it is 16-byte aligned, for storing
// SSE regs. It would be marginally better not to do this. In C++ we
@ -69,7 +70,7 @@ impl Context {
// overflow). Additionally, their coroutine stacks are listed as being
// zero-length, so that's how we detect what's what here.
let stack_base: *const uint = stack.start();
let bounds = if sp as uint == stack_base as uint {
let bounds = if sp as libc::uintptr_t == stack_base as libc::uintptr_t {
None
} else {
Some((stack_base as uint, sp as uint))
@ -166,7 +167,7 @@ fn new_regs() -> Box<Registers> {
#[cfg(target_arch = "x86")]
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
procedure: raw::Procedure, sp: *mut uint) {
let sp = sp as *mut uint;
// x86 has interesting stack alignment requirements, so do some alignment
// plus some offsetting to figure out what the actual stack should be.
let sp = align_down(sp);
@ -188,13 +189,15 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
// windows requires saving more registers (both general and XMM), so the windows
// register context must be larger.
#[cfg(windows, target_arch = "x86_64")]
#[repr(C)]
struct Registers {
gpr:[uint, ..14],
gpr:[libc::uintptr_t, ..14],
_xmm:[simd::u32x4, ..10]
}
#[cfg(not(windows), target_arch = "x86_64")]
#[repr(C)]
struct Registers {
gpr:[uint, ..10],
gpr:[libc::uintptr_t, ..10],
_xmm:[simd::u32x4, ..6]
}
@ -234,30 +237,30 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
unsafe { *sp = 0; }
rtdebug!("creating call frame");
rtdebug!("fptr {:#x}", fptr as uint);
rtdebug!("fptr {:#x}", fptr as libc::uintptr_t);
rtdebug!("arg {:#x}", arg);
rtdebug!("sp {}", sp);
// These registers are frobbed by rust_bootstrap_green_task into the right
// location so we can invoke the "real init function", `fptr`.
regs.gpr[RUSTRT_R12] = arg as uint;
regs.gpr[RUSTRT_R13] = procedure.code as uint;
regs.gpr[RUSTRT_R14] = procedure.env as uint;
regs.gpr[RUSTRT_R15] = fptr as uint;
regs.gpr[RUSTRT_R12] = arg as libc::uintptr_t;
regs.gpr[RUSTRT_R13] = procedure.code as libc::uintptr_t;
regs.gpr[RUSTRT_R14] = procedure.env as libc::uintptr_t;
regs.gpr[RUSTRT_R15] = fptr as libc::uintptr_t;
// These registers are picked up by the regular context switch paths. These
// will put us in "mostly the right context" except for frobbing all the
// arguments to the right place. We have the small trampoline code inside of
// rust_bootstrap_green_task to do that.
regs.gpr[RUSTRT_RSP] = sp as uint;
regs.gpr[RUSTRT_IP] = rust_bootstrap_green_task as uint;
regs.gpr[RUSTRT_RSP] = sp as libc::uintptr_t;
regs.gpr[RUSTRT_IP] = rust_bootstrap_green_task as libc::uintptr_t;
// Last base pointer on the stack should be 0
regs.gpr[RUSTRT_RBP] = 0;
}
#[cfg(target_arch = "arm")]
type Registers = [uint, ..32];
type Registers = [libc::uintptr_t, ..32];
#[cfg(target_arch = "arm")]
fn new_regs() -> Box<Registers> { box {[0, .. 32]} }
@ -277,17 +280,17 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
// ARM uses the same technique as x86_64 to have a landing pad for the start
// of all new green tasks. Neither r1/r2 are saved on a context switch, so
// the shim will copy r3/r4 into r1/r2 and then execute the function in r5
regs[0] = arg as uint; // r0
regs[3] = procedure.code as uint; // r3
regs[4] = procedure.env as uint; // r4
regs[5] = fptr as uint; // r5
regs[13] = sp as uint; // #52 sp, r13
regs[14] = rust_bootstrap_green_task as uint; // #56 pc, r14 --> lr
regs[0] = arg as libc::uintptr_t; // r0
regs[3] = procedure.code as libc::uintptr_t; // r3
regs[4] = procedure.env as libc::uintptr_t; // r4
regs[5] = fptr as libc::uintptr_t; // r5
regs[13] = sp as libc::uintptr_t; // #52 sp, r13
regs[14] = rust_bootstrap_green_task as libc::uintptr_t; // #56 pc, r14 --> lr
}
#[cfg(target_arch = "mips")]
#[cfg(target_arch = "mipsel")]
type Registers = [uint, ..32];
type Registers = [libc::uintptr_t, ..32];
#[cfg(target_arch = "mips")]
#[cfg(target_arch = "mipsel")]
@ -304,12 +307,12 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
// The final return address. 0 indicates the bottom of the stack
unsafe { *sp = 0; }
regs[4] = arg as uint;
regs[5] = procedure.code as uint;
regs[6] = procedure.env as uint;
regs[29] = sp as uint;
regs[25] = fptr as uint;
regs[31] = fptr as uint;
regs[4] = arg as libc::uintptr_t;
regs[5] = procedure.code as libc::uintptr_t;
regs[6] = procedure.env as libc::uintptr_t;
regs[29] = sp as libc::uintptr_t;
regs[25] = fptr as libc::uintptr_t;
regs[31] = fptr as libc::uintptr_t;
}
fn align_down(sp: *mut uint) -> *mut uint {

View File

@ -68,7 +68,8 @@ impl Stack {
// FIXME: Using the FFI to call a C macro. Slow
stk.valgrind_id = unsafe {
rust_valgrind_stack_register(stk.start(), stk.end())
rust_valgrind_stack_register(stk.start() as *const libc::uintptr_t,
stk.end() as *const libc::uintptr_t)
};
return stk;
}

View File

@ -334,6 +334,7 @@ pub mod types {
__variant1,
__variant2,
}
pub enum FILE {}
pub enum fpos_t {}
}
@ -369,6 +370,7 @@ pub mod types {
pub type pthread_t = c_ulong;
#[repr(C)]
pub struct glob_t {
pub gl_pathc: size_t,
pub gl_pathv: *mut *mut c_char,
@ -381,11 +383,13 @@ pub mod types {
pub __unused5: *mut c_void,
}
#[repr(C)]
pub struct timeval {
pub tv_sec: time_t,
pub tv_usec: suseconds_t,
}
#[repr(C)]
pub struct timespec {
pub tv_sec: time_t,
pub tv_nsec: c_long,
@ -402,24 +406,29 @@ pub mod types {
pub type sa_family_t = u16;
pub type in_port_t = u16;
pub type in_addr_t = u32;
#[repr(C)]
pub struct sockaddr {
pub sa_family: sa_family_t,
pub sa_data: [u8, ..14],
}
#[repr(C)]
pub struct sockaddr_storage {
pub ss_family: sa_family_t,
pub __ss_align: i64,
pub __ss_pad2: [u8, ..112],
}
#[repr(C)]
pub struct sockaddr_in {
pub sin_family: sa_family_t,
pub sin_port: in_port_t,
pub sin_addr: in_addr,
pub sin_zero: [u8, ..8],
}
#[repr(C)]
pub struct in_addr {
pub s_addr: in_addr_t,
}
#[repr(C)]
pub struct sockaddr_in6 {
pub sin6_family: sa_family_t,
pub sin6_port: in_port_t,
@ -427,17 +436,21 @@ pub mod types {
pub sin6_addr: in6_addr,
pub sin6_scope_id: u32,
}
#[repr(C)]
pub struct in6_addr {
pub s6_addr: [u16, ..8]
}
#[repr(C)]
pub struct ip_mreq {
pub imr_multiaddr: in_addr,
pub imr_interface: in_addr,
}
#[repr(C)]
pub struct ip6_mreq {
pub ipv6mr_multiaddr: in6_addr,
pub ipv6mr_interface: c_uint,
}
#[repr(C)]
pub struct addrinfo {
pub ai_flags: c_int,
pub ai_family: c_int,
@ -459,6 +472,7 @@ pub mod types {
pub ai_next: *mut addrinfo,
}
#[repr(C)]
pub struct sockaddr_un {
pub sun_family: sa_family_t,
pub sun_path: [c_char, ..108]
@ -493,8 +507,8 @@ pub mod types {
pub mod c99 {
pub type c_longlong = i64;
pub type c_ulonglong = u64;
pub type intptr_t = int;
pub type uintptr_t = uint;
pub type intptr_t = i32;
pub type uintptr_t = u32;
}
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "mips")]
@ -533,6 +547,7 @@ pub mod types {
pub type blksize_t = i32;
pub type blkcnt_t = i32;
#[repr(C)]
pub struct stat {
pub st_dev: dev_t,
pub __pad1: c_short,
@ -556,11 +571,13 @@ pub mod types {
pub __unused5: c_long,
}
#[repr(C)]
pub struct utimbuf {
pub actime: time_t,
pub modtime: time_t,
}
#[repr(C)]
pub struct pthread_attr_t {
pub __size: [u32, ..9]
}
@ -575,6 +592,7 @@ pub mod types {
pub type blksize_t = u32;
pub type blkcnt_t = u32;
#[repr(C)]
pub struct stat {
pub st_dev: c_ulonglong,
pub __pad0: [c_uchar, ..4],
@ -597,11 +615,13 @@ pub mod types {
pub st_ino: c_ulonglong,
}
#[repr(C)]
pub struct utimbuf {
pub actime: time_t,
pub modtime: time_t,
}
#[repr(C)]
pub struct pthread_attr_t {
pub __size: [u32, ..9]
}
@ -618,6 +638,7 @@ pub mod types {
pub type blksize_t = i32;
pub type blkcnt_t = i32;
#[repr(C)]
pub struct stat {
pub st_dev: c_ulong,
pub st_pad1: [c_long, ..3],
@ -641,11 +662,13 @@ pub mod types {
pub st_pad5: [c_long, ..14],
}
#[repr(C)]
pub struct utimbuf {
pub actime: time_t,
pub modtime: time_t,
}
#[repr(C)]
pub struct pthread_attr_t {
pub __size: [u32, ..9]
}
@ -679,8 +702,8 @@ pub mod types {
pub mod c99 {
pub type c_longlong = i64;
pub type c_ulonglong = u64;
pub type intptr_t = int;
pub type uintptr_t = uint;
pub type intptr_t = i64;
pub type uintptr_t = u64;
}
pub mod posix88 {
pub type off_t = i64;
@ -702,6 +725,7 @@ pub mod types {
pub type nlink_t = u64;
pub type blksize_t = i64;
pub type blkcnt_t = i64;
#[repr(C)]
pub struct stat {
pub st_dev: dev_t,
pub st_ino: ino_t,
@ -723,11 +747,13 @@ pub mod types {
pub __unused: [c_long, ..3],
}
#[repr(C)]
pub struct utimbuf {
pub actime: time_t,
pub modtime: time_t,
}
#[repr(C)]
pub struct pthread_attr_t {
pub __size: [u64, ..7]
}
@ -752,6 +778,7 @@ pub mod types {
pub type pthread_t = uintptr_t;
#[repr(C)]
pub struct glob_t {
pub gl_pathc: size_t,
pub __unused1: size_t,
@ -768,11 +795,13 @@ pub mod types {
pub __unused8: *mut c_void,
}
#[repr(C)]
pub struct timeval {
pub tv_sec: time_t,
pub tv_usec: suseconds_t,
}
#[repr(C)]
pub struct timespec {
pub tv_sec: time_t,
pub tv_nsec: c_long,
@ -789,11 +818,13 @@ pub mod types {
pub type sa_family_t = u8;
pub type in_port_t = u16;
pub type in_addr_t = u32;
#[repr(C)]
pub struct sockaddr {
pub sa_len: u8,
pub sa_family: sa_family_t,
pub sa_data: [u8, ..14],
}
#[repr(C)]
pub struct sockaddr_storage {
pub ss_len: u8,
pub ss_family: sa_family_t,
@ -801,6 +832,7 @@ pub mod types {
pub __ss_align: i64,
pub __ss_pad2: [u8, ..112],
}
#[repr(C)]
pub struct sockaddr_in {
pub sin_len: u8,
pub sin_family: sa_family_t,
@ -808,9 +840,11 @@ pub mod types {
pub sin_addr: in_addr,
pub sin_zero: [u8, ..8],
}
#[repr(C)]
pub struct in_addr {
pub s_addr: in_addr_t,
}
#[repr(C)]
pub struct sockaddr_in6 {
pub sin6_len: u8,
pub sin6_family: sa_family_t,
@ -819,17 +853,21 @@ pub mod types {
pub sin6_addr: in6_addr,
pub sin6_scope_id: u32,
}
#[repr(C)]
pub struct in6_addr {
pub s6_addr: [u16, ..8]
}
#[repr(C)]
pub struct ip_mreq {
pub imr_multiaddr: in_addr,
pub imr_interface: in_addr,
}
#[repr(C)]
pub struct ip6_mreq {
pub ipv6mr_multiaddr: in6_addr,
pub ipv6mr_interface: c_uint,
}
#[repr(C)]
pub struct addrinfo {
pub ai_flags: c_int,
pub ai_family: c_int,
@ -840,6 +878,7 @@ pub mod types {
pub ai_addr: *mut sockaddr,
pub ai_next: *mut addrinfo,
}
#[repr(C)]
pub struct sockaddr_un {
pub sun_len: u8,
pub sun_family: sa_family_t,
@ -872,8 +911,8 @@ pub mod types {
pub mod c99 {
pub type c_longlong = i64;
pub type c_ulonglong = u64;
pub type intptr_t = int;
pub type uintptr_t = uint;
pub type intptr_t = i64;
pub type uintptr_t = u64;
}
pub mod posix88 {
pub type off_t = i64;
@ -898,6 +937,7 @@ pub mod types {
pub type blksize_t = i64;
pub type blkcnt_t = i64;
pub type fflags_t = u32;
#[repr(C)]
pub struct stat {
pub st_dev: dev_t,
pub st_ino: ino_t,
@ -923,6 +963,7 @@ pub mod types {
pub __unused: [uint8_t, ..2],
}
#[repr(C)]
pub struct utimbuf {
pub actime: time_t,
pub modtime: time_t,
@ -950,6 +991,7 @@ pub mod types {
pub type pthread_t = uintptr_t;
#[repr(C)]
pub struct glob_t {
pub gl_pathc: size_t,
pub __unused1: size_t,
@ -966,11 +1008,13 @@ pub mod types {
pub __unused8: *mut c_void,
}
#[repr(C)]
pub struct timeval {
pub tv_sec: time_t,
pub tv_usec: suseconds_t,
}
#[repr(C)]
pub struct timespec {
pub tv_sec: time_t,
pub tv_nsec: c_long,
@ -987,11 +1031,13 @@ pub mod types {
pub type sa_family_t = u8;
pub type in_port_t = u16;
pub type in_addr_t = u32;
#[repr(C)]
pub struct sockaddr {
pub sa_len: u8,
pub sa_family: sa_family_t,
pub sa_data: [u8, ..14],
}
#[repr(C)]
pub struct sockaddr_storage {
pub ss_len: u8,
pub ss_family: sa_family_t,
@ -999,6 +1045,7 @@ pub mod types {
pub __ss_align: i64,
pub __ss_pad2: [u8, ..112],
}
#[repr(C)]
pub struct sockaddr_in {
pub sin_len: u8,
pub sin_family: sa_family_t,
@ -1006,9 +1053,11 @@ pub mod types {
pub sin_addr: in_addr,
pub sin_zero: [u8, ..8],
}
#[repr(C)]
pub struct in_addr {
pub s_addr: in_addr_t,
}
#[repr(C)]
pub struct sockaddr_in6 {
pub sin6_len: u8,
pub sin6_family: sa_family_t,
@ -1017,17 +1066,21 @@ pub mod types {
pub sin6_addr: in6_addr,
pub sin6_scope_id: u32,
}
#[repr(C)]
pub struct in6_addr {
pub s6_addr: [u16, ..8]
}
#[repr(C)]
pub struct ip_mreq {
pub imr_multiaddr: in_addr,
pub imr_interface: in_addr,
}
#[repr(C)]
pub struct ip6_mreq {
pub ipv6mr_multiaddr: in6_addr,
pub ipv6mr_interface: c_uint,
}
#[repr(C)]
pub struct addrinfo {
pub ai_flags: c_int,
pub ai_family: c_int,
@ -1038,6 +1091,7 @@ pub mod types {
pub ai_addr: *mut sockaddr,
pub ai_next: *mut addrinfo,
}
#[repr(C)]
pub struct sockaddr_un {
pub sun_len: u8,
pub sun_family: sa_family_t,
@ -1070,8 +1124,8 @@ pub mod types {
pub mod c99 {
pub type c_longlong = i64;
pub type c_ulonglong = u64;
pub type intptr_t = int;
pub type uintptr_t = uint;
pub type intptr_t = i64;
pub type uintptr_t = u64;
}
pub mod posix88 {
pub type off_t = i64;
@ -1098,6 +1152,7 @@ pub mod types {
pub type blkcnt_t = i64;
pub type fflags_t = u32;
#[repr(C)]
pub struct stat {
pub st_ino: ino_t,
pub st_nlink: nlink_t,
@ -1122,6 +1177,7 @@ pub mod types {
pub st_qspare1: int64_t,
pub st_qspare2: int64_t,
}
#[repr(C)]
pub struct utimbuf {
pub actime: time_t,
pub modtime: time_t,
@ -1149,6 +1205,7 @@ pub mod types {
// pub Note: this is the struct called stat64 in win32. Not stat,
// nor stati64.
#[repr(C)]
pub struct stat {
pub st_dev: dev_t,
pub st_ino: ino_t,
@ -1164,16 +1221,19 @@ pub mod types {
}
// note that this is called utimbuf64 in win32
#[repr(C)]
pub struct utimbuf {
pub actime: time64_t,
pub modtime: time64_t,
}
#[repr(C)]
pub struct timeval {
pub tv_sec: c_long,
pub tv_usec: c_long,
}
#[repr(C)]
pub struct timespec {
pub tv_sec: time_t,
pub tv_nsec: c_long,
@ -1184,31 +1244,37 @@ pub mod types {
pub mod bsd44 {
use types::os::arch::c95::{c_char, c_int, c_uint, size_t};
use types::os::arch::c99::uintptr_t;
pub type SOCKET = uint;
pub type SOCKET = uintptr_t;
pub type socklen_t = c_int;
pub type sa_family_t = u16;
pub type in_port_t = u16;
pub type in_addr_t = u32;
#[repr(C)]
pub struct sockaddr {
pub sa_family: sa_family_t,
pub sa_data: [u8, ..14],
}
#[repr(C)]
pub struct sockaddr_storage {
pub ss_family: sa_family_t,
pub __ss_pad1: [u8, ..6],
pub __ss_align: i64,
pub __ss_pad2: [u8, ..112],
}
#[repr(C)]
pub struct sockaddr_in {
pub sin_family: sa_family_t,
pub sin_port: in_port_t,
pub sin_addr: in_addr,
pub sin_zero: [u8, ..8],
}
#[repr(C)]
pub struct in_addr {
pub s_addr: in_addr_t,
}
#[repr(C)]
pub struct sockaddr_in6 {
pub sin6_family: sa_family_t,
pub sin6_port: in_port_t,
@ -1216,17 +1282,21 @@ pub mod types {
pub sin6_addr: in6_addr,
pub sin6_scope_id: u32,
}
#[repr(C)]
pub struct in6_addr {
pub s6_addr: [u16, ..8]
}
#[repr(C)]
pub struct ip_mreq {
pub imr_multiaddr: in_addr,
pub imr_interface: in_addr,
}
#[repr(C)]
pub struct ip6_mreq {
pub ipv6mr_multiaddr: in6_addr,
pub ipv6mr_interface: c_uint,
}
#[repr(C)]
pub struct addrinfo {
pub ai_flags: c_int,
pub ai_family: c_int,
@ -1237,6 +1307,7 @@ pub mod types {
pub ai_addr: *mut sockaddr,
pub ai_next: *mut addrinfo,
}
#[repr(C)]
pub struct sockaddr_un {
pub sun_family: sa_family_t,
pub sun_path: [c_char, ..108]
@ -1286,8 +1357,8 @@ pub mod types {
pub mod c99 {
pub type c_longlong = i64;
pub type c_ulonglong = u64;
pub type intptr_t = int;
pub type uintptr_t = uint;
pub type intptr_t = i32;
pub type uintptr_t = u32;
}
pub mod posix88 {
@ -1319,7 +1390,7 @@ pub mod types {
use types::os::arch::c95::{c_char, c_int, c_uint, size_t};
use types::os::arch::c95::{c_long, c_ulong};
use types::os::arch::c95::{wchar_t};
use types::os::arch::c99::{c_ulonglong, c_longlong};
use types::os::arch::c99::{c_ulonglong, c_longlong, uintptr_t};
pub type BOOL = c_int;
pub type BYTE = u8;
@ -1353,6 +1424,7 @@ pub mod types {
pub type LPWCH = *mut WCHAR;
pub type LPCH = *mut CHAR;
#[repr(C)]
pub struct SECURITY_ATTRIBUTES {
pub nLength: DWORD,
pub lpSecurityDescriptor: LPVOID,
@ -1376,6 +1448,7 @@ pub mod types {
pub type time64_t = i64;
pub type int64 = i64;
#[repr(C)]
pub struct STARTUPINFO {
pub cb: DWORD,
pub lpReserved: LPWSTR,
@ -1398,6 +1471,7 @@ pub mod types {
}
pub type LPSTARTUPINFO = *mut STARTUPINFO;
#[repr(C)]
pub struct PROCESS_INFORMATION {
pub hProcess: HANDLE,
pub hThread: HANDLE,
@ -1406,13 +1480,14 @@ pub mod types {
}
pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION;
#[repr(C)]
pub struct SYSTEM_INFO {
pub wProcessorArchitecture: WORD,
pub wReserved: WORD,
pub dwPageSize: DWORD,
pub lpMinimumApplicationAddress: LPVOID,
pub lpMaximumApplicationAddress: LPVOID,
pub dwActiveProcessorMask: uint,
pub dwActiveProcessorMask: uintptr_t,
pub dwNumberOfProcessors: DWORD,
pub dwProcessorType: DWORD,
pub dwAllocationGranularity: DWORD,
@ -1421,6 +1496,7 @@ pub mod types {
}
pub type LPSYSTEM_INFO = *mut SYSTEM_INFO;
#[repr(C)]
pub struct MEMORY_BASIC_INFORMATION {
pub BaseAddress: LPVOID,
pub AllocationBase: LPVOID,
@ -1432,6 +1508,7 @@ pub mod types {
}
pub type LPMEMORY_BASIC_INFORMATION = *mut MEMORY_BASIC_INFORMATION;
#[repr(C)]
pub struct OVERLAPPED {
pub Internal: *mut c_ulong,
pub InternalHigh: *mut c_ulong,
@ -1442,6 +1519,7 @@ pub mod types {
pub type LPOVERLAPPED = *mut OVERLAPPED;
#[repr(C)]
pub struct FILETIME {
pub dwLowDateTime: DWORD,
pub dwHighDateTime: DWORD,
@ -1449,6 +1527,7 @@ pub mod types {
pub type LPFILETIME = *mut FILETIME;
#[repr(C)]
pub struct GUID {
pub Data1: DWORD,
pub Data2: WORD,
@ -1456,6 +1535,7 @@ pub mod types {
pub Data4: [BYTE, ..8],
}
#[repr(C)]
pub struct WSAPROTOCOLCHAIN {
pub ChainLen: c_int,
pub ChainEntries: [DWORD, ..MAX_PROTOCOL_CHAIN as uint],
@ -1463,6 +1543,7 @@ pub mod types {
pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN;
#[repr(C)]
pub struct WSAPROTOCOL_INFO {
pub dwServiceFlags1: DWORD,
pub dwServiceFlags2: DWORD,
@ -1505,6 +1586,7 @@ pub mod types {
pub type pthread_t = uintptr_t;
#[repr(C)]
pub struct glob_t {
pub gl_pathc: size_t,
pub __unused1: c_int,
@ -1521,11 +1603,13 @@ pub mod types {
pub __unused8: *mut c_void,
}
#[repr(C)]
pub struct timeval {
pub tv_sec: time_t,
pub tv_usec: suseconds_t,
}
#[repr(C)]
pub struct timespec {
pub tv_sec: time_t,
pub tv_nsec: c_long,
@ -1543,11 +1627,13 @@ pub mod types {
pub type sa_family_t = u8;
pub type in_port_t = u16;
pub type in_addr_t = u32;
#[repr(C)]
pub struct sockaddr {
pub sa_len: u8,
pub sa_family: sa_family_t,
pub sa_data: [u8, ..14],
}
#[repr(C)]
pub struct sockaddr_storage {
pub ss_len: u8,
pub ss_family: sa_family_t,
@ -1555,6 +1641,7 @@ pub mod types {
pub __ss_align: i64,
pub __ss_pad2: [u8, ..112],
}
#[repr(C)]
pub struct sockaddr_in {
pub sin_len: u8,
pub sin_family: sa_family_t,
@ -1562,9 +1649,11 @@ pub mod types {
pub sin_addr: in_addr,
pub sin_zero: [u8, ..8],
}
#[repr(C)]
pub struct in_addr {
pub s_addr: in_addr_t,
}
#[repr(C)]
pub struct sockaddr_in6 {
pub sin6_len: u8,
pub sin6_family: sa_family_t,
@ -1573,17 +1662,21 @@ pub mod types {
pub sin6_addr: in6_addr,
pub sin6_scope_id: u32,
}
#[repr(C)]
pub struct in6_addr {
pub s6_addr: [u16, ..8]
}
#[repr(C)]
pub struct ip_mreq {
pub imr_multiaddr: in_addr,
pub imr_interface: in_addr,
}
#[repr(C)]
pub struct ip6_mreq {
pub ipv6mr_multiaddr: in6_addr,
pub ipv6mr_interface: c_uint,
}
#[repr(C)]
pub struct addrinfo {
pub ai_flags: c_int,
pub ai_family: c_int,
@ -1594,6 +1687,7 @@ pub mod types {
pub ai_addr: *mut sockaddr,
pub ai_next: *mut addrinfo,
}
#[repr(C)]
pub struct sockaddr_un {
pub sun_len: u8,
pub sun_family: sa_family_t,
@ -1627,8 +1721,8 @@ pub mod types {
pub mod c99 {
pub type c_longlong = i64;
pub type c_ulonglong = u64;
pub type intptr_t = int;
pub type uintptr_t = uint;
pub type intptr_t = i32;
pub type uintptr_t = u32;
}
pub mod posix88 {
pub type off_t = i64;
@ -1651,6 +1745,7 @@ pub mod types {
pub type blksize_t = i64;
pub type blkcnt_t = i32;
#[repr(C)]
pub struct stat {
pub st_dev: dev_t,
pub st_mode: mode_t,
@ -1676,11 +1771,13 @@ pub mod types {
pub st_qspare: [int64_t, ..2],
}
#[repr(C)]
pub struct utimbuf {
pub actime: time_t,
pub modtime: time_t,
}
#[repr(C)]
pub struct pthread_attr_t {
pub __sig: c_long,
pub __opaque: [c_char, ..36]
@ -1691,6 +1788,7 @@ pub mod types {
pub mod bsd44 {
}
pub mod extra {
#[repr(C)]
pub struct mach_timebase_info {
pub numer: u32,
pub denom: u32,
@ -1724,8 +1822,8 @@ pub mod types {
pub mod c99 {
pub type c_longlong = i64;
pub type c_ulonglong = u64;
pub type intptr_t = int;
pub type uintptr_t = uint;
pub type intptr_t = i64;
pub type uintptr_t = u64;
}
pub mod posix88 {
pub type off_t = i64;
@ -1749,6 +1847,7 @@ pub mod types {
pub type blksize_t = i64;
pub type blkcnt_t = i32;
#[repr(C)]
pub struct stat {
pub st_dev: dev_t,
pub st_mode: mode_t,
@ -1774,11 +1873,13 @@ pub mod types {
pub st_qspare: [int64_t, ..2],
}
#[repr(C)]
pub struct utimbuf {
pub actime: time_t,
pub modtime: time_t,
}
#[repr(C)]
pub struct pthread_attr_t {
pub __sig: c_long,
pub __opaque: [c_char, ..56]
@ -1789,6 +1890,7 @@ pub mod types {
pub mod bsd44 {
}
pub mod extra {
#[repr(C)]
pub struct mach_timebase_info {
pub numer: u32,
pub denom: u32,
@ -4300,7 +4402,7 @@ pub mod funcs {
pub fn glob(pattern: *const c_char,
flags: c_int,
errfunc: ::Nullable<extern "C" fn(epath: *const c_char,
errno: int) -> int>,
errno: c_int) -> int>,
pglob: *mut glob_t);
pub fn globfree(pglob: *mut glob_t);
}

View File

@ -91,6 +91,7 @@ extern {
mod select {
pub static FD_SETSIZE: uint = 1024;
#[repr(C)]
pub struct fd_set {
fds_bits: [i32, ..(FD_SETSIZE / 32)]
}
@ -106,12 +107,14 @@ mod select {
#[cfg(target_os = "linux")]
mod select {
use std::uint;
use libc;
pub static FD_SETSIZE: uint = 1024;
#[repr(C)]
pub struct fd_set {
// FIXME: shouldn't this be a c_ulong?
fds_bits: [uint, ..(FD_SETSIZE / uint::BITS)]
fds_bits: [libc::uintptr_t, ..(FD_SETSIZE / uint::BITS)]
}
pub fn fd_set(set: &mut fd_set, fd: i32) {
@ -139,6 +142,7 @@ mod signal {
// This definition is not as accurate as it could be, {pid, uid, status} is
// actually a giant union. Currently we're only interested in these fields,
// however.
#[repr(C)]
pub struct siginfo {
si_signo: libc::c_int,
si_errno: libc::c_int,
@ -148,6 +152,7 @@ mod signal {
pub status: libc::c_int,
}
#[repr(C)]
pub struct sigaction {
pub sa_handler: extern fn(libc::c_int),
pub sa_mask: sigset_t,
@ -155,10 +160,13 @@ mod signal {
sa_restorer: *mut libc::c_void,
}
#[repr(C)]
#[cfg(target_word_size = "32")]
pub struct sigset_t {
__val: [libc::c_ulong, ..32],
}
#[repr(C)]
#[cfg(target_word_size = "64")]
pub struct sigset_t {
__val: [libc::c_ulong, ..16],
@ -182,6 +190,7 @@ mod signal {
// This definition is not as accurate as it could be, {pid, uid, status} is
// actually a giant union. Currently we're only interested in these fields,
// however.
#[repr(C)]
pub struct siginfo {
si_signo: libc::c_int,
si_code: libc::c_int,
@ -191,6 +200,7 @@ mod signal {
pub status: libc::c_int,
}
#[repr(C)]
pub struct sigaction {
pub sa_flags: libc::c_uint,
pub sa_handler: extern fn(libc::c_int),
@ -199,6 +209,7 @@ mod signal {
sa_resv: [libc::c_int, ..1],
}
#[repr(C)]
pub struct sigset_t {
__val: [libc::c_ulong, ..32],
}
@ -225,12 +236,14 @@ mod signal {
pub type sigset_t = u32;
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "dragonfly")]
#[repr(C)]
pub struct sigset_t {
bits: [u32, ..4],
}
// This structure has more fields, but we're not all that interested in
// them.
#[repr(C)]
pub struct siginfo {
pub si_signo: libc::c_int,
pub si_errno: libc::c_int,
@ -242,6 +255,7 @@ mod signal {
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
#[repr(C)]
pub struct sigaction {
pub sa_handler: extern fn(libc::c_int),
sa_tramp: *mut libc::c_void,
@ -251,6 +265,7 @@ mod signal {
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "dragonfly")]
#[repr(C)]
pub struct sigaction {
pub sa_handler: extern fn(libc::c_int),
pub sa_flags: libc::c_int,

View File

@ -27,7 +27,6 @@
use metadata::csearch;
use middle::def::*;
use middle::trans::adt; // for `adt::is_ffi_safe`
use middle::typeck::astconv::ast_ty_to_ty;
use middle::typeck::infer;
use middle::{typeck, ty, def, pat_util, stability};
@ -362,12 +361,17 @@ impl LintPass for CTypes {
"found rust type `uint` in foreign module, while \
libc::c_uint or libc::c_ulong should be used");
}
def::DefTy(def_id) => {
if !adt::is_ffi_safe(cx.tcx, def_id) {
def::DefTy(..) => {
let tty = match cx.tcx.ast_ty_to_ty_cache.borrow().find(&ty.id) {
Some(&ty::atttce_resolved(t)) => t,
_ => fail!("ast_ty_to_ty_cache was incomplete after typeck!")
};
if !ty::is_ffi_safe(cx.tcx, tty) {
cx.span_lint(CTYPES, ty.span,
"found enum type without foreign-function-safe
"found type without foreign-function-safe
representation annotation in foreign module, consider \
adding a #[repr(...)] attribute to the enumeration");
adding a #[repr(...)] attribute to the type");
}
}
_ => ()
@ -770,9 +774,10 @@ impl LintPass for NonCamelCaseTypes {
}
}
let has_extern_repr = it.attrs.iter().fold(attr::ReprAny, |acc, attr| {
attr::find_repr_attr(cx.tcx.sess.diagnostic(), attr, acc)
}) == attr::ReprExtern;
let has_extern_repr = it.attrs.iter().map(|attr| {
attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr).iter()
.any(|r| r == &attr::ReprExtern)
}).any(|x| x);
if has_extern_repr { return }
match it.node {
@ -783,6 +788,7 @@ impl LintPass for NonCamelCaseTypes {
check_case(cx, "trait", it.ident, it.span)
}
ast::ItemEnum(ref enum_definition, _) => {
if has_extern_repr { return }
check_case(cx, "type", it.ident, it.span);
for variant in enum_definition.variants.iter() {
check_case(cx, "variant", variant.node.name, variant.span);

View File

@ -195,9 +195,10 @@ impl<'a> MarkSymbolVisitor<'a> {
ast_map::NodeItem(item) => {
match item.node {
ast::ItemStruct(..) => {
let has_extern_repr = item.attrs.iter().fold(attr::ReprAny, |acc, attr| {
attr::find_repr_attr(self.tcx.sess.diagnostic(), attr, acc)
}) == attr::ReprExtern;
let has_extern_repr = item.attrs.iter().fold(false, |acc, attr| {
acc || attr::find_repr_attrs(self.tcx.sess.diagnostic(), attr)
.iter().any(|&x| x == attr::ReprExtern)
});
visit::walk_item(self, &*item, MarkSymbolVisitorContext {
struct_has_extern_repr: has_extern_repr,

View File

@ -46,6 +46,8 @@
#![allow(unsigned_negate)]
use libc::c_ulonglong;
use std::collections::Map;
use std::num::Int;
use std::rc::Rc;
use llvm::{ValueRef, True, IntEQ, IntNE};
@ -178,7 +180,8 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
}
ty::ty_enum(def_id, ref substs) => {
let cases = get_cases(cx.tcx(), def_id, substs);
let hint = ty::lookup_repr_hint(cx.tcx(), def_id);
let hint = *ty::lookup_repr_hints(cx.tcx(), def_id).as_slice().get(0)
.unwrap_or(&attr::ReprAny);
let dtor = ty::ty_dtor(cx.tcx(), def_id).has_drop_flag();
@ -266,36 +269,6 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
}
}
/// Determine, without doing translation, whether an ADT must be FFI-safe.
/// For use in lint or similar, where being sound but slightly incomplete is acceptable.
pub fn is_ffi_safe(tcx: &ty::ctxt, def_id: ast::DefId) -> bool {
match ty::get(ty::lookup_item_type(tcx, def_id).ty).sty {
ty::ty_enum(def_id, _) => {
let variants = ty::enum_variants(tcx, def_id);
// Univariant => like struct/tuple.
if variants.len() <= 1 {
return true;
}
let hint = ty::lookup_repr_hint(tcx, def_id);
// Appropriate representation explicitly selected?
if hint.is_ffi_safe() {
return true;
}
// Option<Box<T>> and similar are used in FFI. Rather than try to
// resolve type parameters and recognize this case exactly, this
// overapproximates -- assuming that if a non-C-like enum is being
// used in FFI then the user knows what they're doing.
if variants.iter().any(|vi| !vi.args.is_empty()) {
return true;
}
false
}
// struct, tuple, etc.
// (is this right in the present of typedefs?)
_ => true
}
}
// this should probably all be in ty
struct Case {
discr: Disr,
@ -427,6 +400,9 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp
}
attr::ReprAny => {
attempts = choose_shortest;
},
attr::ReprPacked => {
cx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
}
}
for &ity in attempts.iter() {

View File

@ -482,7 +482,7 @@ pub struct t { inner: *const t_opaque }
impl fmt::Show for t {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
"*t_opaque".fmt(f)
write!(f, "{}", get(*self))
}
}
@ -791,6 +791,13 @@ pub enum sty {
ty_int(ast::IntTy),
ty_uint(ast::UintTy),
ty_float(ast::FloatTy),
/// Substs here, possibly against intuition, *may* contain `ty_param`s.
/// That is, even after substitution it is possible that there are type
/// variables. This happens when the `ty_enum` corresponds to an enum
/// definition and not a concerete use of it. To get the correct `ty_enum`
/// from the tcx, use the `NodeId` from the `ast::Ty` and look it up in
/// the `ast_ty_to_ty_cache`. This is probably true for `ty_struct` as
/// well.`
ty_enum(DefId, Substs),
ty_box(t),
ty_uniq(t),
@ -1981,7 +1988,8 @@ def_type_content_sets!(
// ReachesManaged /* see [1] below */ = 0b0000_0100__0000_0000__0000,
ReachesMutable = 0b0000_1000__0000_0000__0000,
ReachesNoSync = 0b0001_0000__0000_0000__0000,
ReachesAll = 0b0001_1111__0000_0000__0000,
ReachesFfiUnsafe = 0b0010_0000__0000_0000__0000,
ReachesAll = 0b0011_1111__0000_0000__0000,
// Things that cause values to *move* rather than *copy*
Moves = 0b0000_0000__0000_1011__0000,
@ -2218,6 +2226,11 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
cache.insert(ty_id, TC::None);
let result = match get(ty).sty {
// uint and int are ffi-unsafe
ty_uint(ast::TyU) | ty_int(ast::TyI) => {
TC::ReachesFfiUnsafe
}
// Scalar and unique types are sendable, and durable
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_bare_fn(_) | ty::ty_char | ty_str => {
@ -2225,22 +2238,22 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
}
ty_closure(ref c) => {
closure_contents(cx, &**c)
closure_contents(cx, &**c) | TC::ReachesFfiUnsafe
}
ty_box(typ) => {
tc_ty(cx, typ, cache).managed_pointer()
tc_ty(cx, typ, cache).managed_pointer() | TC::ReachesFfiUnsafe
}
ty_uniq(typ) => {
match get(typ).sty {
TC::ReachesFfiUnsafe | match get(typ).sty {
ty_str => TC::OwnsOwned,
_ => tc_ty(cx, typ, cache).owned_pointer(),
}
}
ty_trait(box ty::TyTrait { bounds, .. }) => {
object_contents(cx, bounds)
object_contents(cx, bounds) | TC::ReachesFfiUnsafe
}
ty_ptr(ref mt) => {
@ -2248,8 +2261,9 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
}
ty_rptr(r, ref mt) => {
match get(mt.ty).sty {
TC::ReachesFfiUnsafe | match get(mt.ty).sty {
ty_str => borrowed_contents(r, ast::MutImmutable),
ty_vec(..) => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(r, mt.mutbl)),
_ => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(r, mt.mutbl)),
}
}
@ -2263,6 +2277,11 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
let mut res =
TypeContents::union(flds.as_slice(),
|f| tc_mt(cx, f.mt, cache));
if !lookup_repr_hints(cx, did).contains(&attr::ReprExtern) {
res = res | TC::ReachesFfiUnsafe;
}
if ty::has_dtor(cx, did) {
res = res | TC::OwnsDtor;
}
@ -2292,9 +2311,49 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
tc_ty(cx, *arg_ty, cache)
})
});
if ty::has_dtor(cx, did) {
res = res | TC::OwnsDtor;
}
if variants.len() != 0 {
let repr_hints = lookup_repr_hints(cx, did);
if repr_hints.len() > 1 {
// this is an error later on, but this type isn't safe
res = res | TC::ReachesFfiUnsafe;
}
match repr_hints.as_slice().get(0) {
Some(h) => if !h.is_ffi_safe() {
res = res | TC::ReachesFfiUnsafe;
},
// ReprAny
None => {
res = res | TC::ReachesFfiUnsafe;
// We allow ReprAny enums if they are eligible for
// the nullable pointer optimization and the
// contained type is an `extern fn`
if variants.len() == 2 {
let mut data_idx = 0;
if variants.get(0).args.len() == 0 {
data_idx = 1;
}
if variants.get(data_idx).args.len() == 1 {
match get(*variants.get(data_idx).args.get(0)).sty {
ty_bare_fn(..) => { res = res - TC::ReachesFfiUnsafe; }
_ => { }
}
}
}
}
}
}
apply_lang_items(cx, did, res)
}
@ -2446,6 +2505,10 @@ pub fn type_moves_by_default(cx: &ctxt, ty: t) -> bool {
type_contents(cx, ty).moves_by_default(cx)
}
pub fn is_ffi_safe(cx: &ctxt, ty: t) -> bool {
!type_contents(cx, ty).intersects(TC::ReachesFfiUnsafe)
}
// True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
pub fn is_instantiable(cx: &ctxt, r_ty: t) -> bool {
fn type_requires(cx: &ctxt, seen: &mut Vec<DefId>,
@ -3968,7 +4031,7 @@ pub fn substd_enum_variants(cx: &ctxt,
-> Vec<Rc<VariantInfo>> {
enum_variants(cx, id).iter().map(|variant_info| {
let substd_args = variant_info.args.iter()
.map(|aty| aty.subst(cx, substs)).collect();
.map(|aty| aty.subst(cx, substs)).collect::<Vec<_>>();
let substd_ctor_ty = variant_info.ctor_ty.subst(cx, substs);
@ -4191,9 +4254,9 @@ pub fn has_attr(tcx: &ctxt, did: DefId, attr: &str) -> bool {
found
}
/// Determine whether an item is annotated with `#[packed]`
/// Determine whether an item is annotated with `#[repr(packed)]`
pub fn lookup_packed(tcx: &ctxt, did: DefId) -> bool {
has_attr(tcx, did, "packed")
lookup_repr_hints(tcx, did).contains(&attr::ReprPacked)
}
/// Determine whether an item is annotated with `#[simd]`
@ -4201,14 +4264,16 @@ pub fn lookup_simd(tcx: &ctxt, did: DefId) -> bool {
has_attr(tcx, did, "simd")
}
// Obtain the representation annotation for a definition.
pub fn lookup_repr_hint(tcx: &ctxt, did: DefId) -> attr::ReprAttr {
let mut acc = attr::ReprAny;
/// Obtain the representation annotation for a struct definition.
pub fn lookup_repr_hints(tcx: &ctxt, did: DefId) -> Vec<attr::ReprAttr> {
let mut acc = Vec::new();
ty::each_attr(tcx, did, |meta| {
acc = attr::find_repr_attr(tcx.sess.diagnostic(), meta, acc);
acc.extend(attr::find_repr_attrs(tcx.sess.diagnostic(), meta).move_iter());
true
});
return acc;
acc
}
// Look up a field ID, whether or not it's local

View File

@ -4217,13 +4217,13 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
let inh = blank_inherited_fields(ccx);
let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
let declty = match hint {
attr::ReprAny | attr::ReprExtern => ty::mk_int(),
attr::ReprAny | attr::ReprPacked | attr::ReprExtern => ty::mk_int(),
attr::ReprInt(_, attr::SignedInt(ity)) => {
ty::mk_mach_int(ity)
}
attr::ReprInt(_, attr::UnsignedInt(ity)) => {
ty::mk_mach_uint(ity)
}
},
};
check_const_with_ty(&fcx, e.span, &*e, declty);
// check_expr (from check_const pass) doesn't guarantee
@ -4262,6 +4262,9 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
"discriminant type specified here");
}
}
attr::ReprPacked => {
ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
}
}
disr_vals.push(current_disr_val);
@ -4275,7 +4278,9 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
return variants;
}
let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
.as_slice().get(0).unwrap_or(&attr::ReprAny);
if hint != attr::ReprAny && vs.len() <= 1 {
if vs.len() == 1 {
span_err!(ccx.tcx.sess, sp, E0083,

View File

@ -65,6 +65,7 @@ static HOEDOWN_EXTENSIONS: libc::c_uint =
type hoedown_document = libc::c_void; // this is opaque to us
#[repr(C)]
struct hoedown_renderer {
opaque: *mut hoedown_html_renderer_state,
blockcode: Option<extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
@ -78,6 +79,7 @@ struct hoedown_renderer {
other: [libc::size_t, ..28],
}
#[repr(C)]
struct hoedown_html_renderer_state {
opaque: *mut libc::c_void,
toc_data: html_toc_data,
@ -87,6 +89,7 @@ struct hoedown_html_renderer_state {
*mut libc::c_void)>,
}
#[repr(C)]
struct html_toc_data {
header_count: libc::c_int,
current_level: libc::c_int,
@ -100,6 +103,7 @@ struct MyOpaque {
toc_builder: Option<TocBuilder>,
}
#[repr(C)]
struct hoedown_buffer {
data: *const u8,
size: libc::size_t,

View File

@ -72,6 +72,7 @@ pub static unwinder_private_data_size: uint = 5;
#[cfg(target_arch = "mipsel")]
pub static unwinder_private_data_size: uint = 2;
#[repr(C)]
pub struct _Unwind_Exception {
pub exception_class: _Unwind_Exception_Class,
pub exception_cleanup: _Unwind_Exception_Cleanup_Fn,

View File

@ -103,6 +103,7 @@ pub type uv_buf_len_t = libc::size_t;
pub type uv_buf_len_t = libc::c_ulong;
// see libuv/include/uv-unix.h
#[repr(C)]
#[cfg(unix)]
pub struct uv_buf_t {
pub base: *mut u8,
@ -114,6 +115,7 @@ pub type uv_os_socket_t = c_int;
// see libuv/include/uv-win.h
#[cfg(windows)]
#[repr(C)]
pub struct uv_buf_t {
pub len: uv_buf_len_t,
pub base: *mut u8,
@ -135,6 +137,7 @@ pub enum uv_poll_event {
UV_WRITABLE = 2,
}
#[repr(C)]
pub struct uv_process_options_t {
pub exit_cb: uv_exit_cb,
pub file: *const libc::c_char,
@ -178,11 +181,13 @@ pub type uv_tty_t = c_void;
pub type uv_signal_t = c_void;
pub type uv_shutdown_t = c_void;
#[repr(C)]
pub struct uv_timespec_t {
pub tv_sec: libc::c_long,
pub tv_nsec: libc::c_long
}
#[repr(C)]
pub struct uv_stat_t {
pub st_dev: libc::uint64_t,
pub st_mode: libc::uint64_t,
@ -373,14 +378,14 @@ pub unsafe fn free_req(v: *mut c_void) {
#[test]
fn handle_sanity_check() {
unsafe {
assert_eq!(UV_HANDLE_TYPE_MAX as uint, rust_uv_handle_type_max());
assert_eq!(UV_HANDLE_TYPE_MAX as libc::uintptr_t, rust_uv_handle_type_max());
}
}
#[test]
fn request_sanity_check() {
unsafe {
assert_eq!(UV_REQ_TYPE_MAX as uint, rust_uv_req_type_max());
assert_eq!(UV_REQ_TYPE_MAX as libc::uintptr_t, rust_uv_req_type_max());
}
}

View File

@ -146,6 +146,7 @@ mod darwin_fd_limit {
use libc;
type rlim_t = libc::uint64_t;
#[repr(C)]
struct rlimit {
rlim_cur: rlim_t,
rlim_max: rlim_t

View File

@ -59,7 +59,7 @@ use libc::c_char;
/// Get the number of cores available
pub fn num_cpus() -> uint {
unsafe {
return rust_get_num_cpus();
return rust_get_num_cpus() as uint;
}
extern {

View File

@ -701,6 +701,7 @@ mod imp {
static IMAGE_FILE_MACHINE_IA64: libc::DWORD = 0x0200;
static IMAGE_FILE_MACHINE_AMD64: libc::DWORD = 0x8664;
#[cfg(stage0)]
#[packed]
struct SYMBOL_INFO {
SizeOfStruct: libc::c_ulong,
@ -723,6 +724,30 @@ mod imp {
Name: [libc::c_char, ..MAX_SYM_NAME],
}
#[cfg(not(stage0))]
#[repr(C, packed)]
struct SYMBOL_INFO {
SizeOfStruct: libc::c_ulong,
TypeIndex: libc::c_ulong,
Reserved: [u64, ..2],
Index: libc::c_ulong,
Size: libc::c_ulong,
ModBase: u64,
Flags: libc::c_ulong,
Value: u64,
Address: u64,
Register: libc::c_ulong,
Scope: libc::c_ulong,
Tag: libc::c_ulong,
NameLen: libc::c_ulong,
MaxNameLen: libc::c_ulong,
// note that windows has this as 1, but it basically just means that
// the name is inline at the end of the struct. For us, we just bump
// the struct size up to MAX_SYM_NAME.
Name: [libc::c_char, ..MAX_SYM_NAME],
}
#[repr(C)]
enum ADDRESS_MODE {
AddrMode1616,
@ -772,6 +797,7 @@ mod imp {
static MAXIMUM_SUPPORTED_EXTENSION: uint = 512;
#[repr(C)]
pub struct CONTEXT {
ContextFlags: libc::DWORD,
Dr0: libc::DWORD,
@ -800,6 +826,7 @@ mod imp {
ExtendedRegisters: [u8, ..MAXIMUM_SUPPORTED_EXTENSION],
}
#[repr(C)]
pub struct FLOATING_SAVE_AREA {
ControlWord: libc::DWORD,
StatusWord: libc::DWORD,
@ -829,6 +856,7 @@ mod imp {
use libc::{c_longlong, c_ulonglong};
use libc::types::os::arch::extra::{WORD, DWORD, DWORDLONG};
#[repr(C)]
pub struct CONTEXT {
P1Home: DWORDLONG,
P2Home: DWORDLONG,
@ -886,11 +914,13 @@ mod imp {
LastExceptionFromRip: DWORDLONG,
}
#[repr(C)]
pub struct M128A {
Low: c_ulonglong,
High: c_longlong
}
#[repr(C)]
pub struct FLOATING_SAVE_AREA {
_Dummy: [u8, ..512] // FIXME: Fill this out
}
@ -907,6 +937,7 @@ mod imp {
}
}
#[repr(C)]
struct Cleanup {
handle: libc::HANDLE,
SymCleanup: SymCleanupFn,

View File

@ -418,19 +418,14 @@ pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[Gc<MetaItem>]) {
}
/// Fold this over attributes to parse #[repr(...)] forms.
/// Parse #[repr(...)] forms.
///
/// Valid repr contents: any of the primitive integral type names (see
/// `int_type_of_word`, below) to specify the discriminant type; and `C`, to use
/// the same discriminant size that the corresponding C enum would. These are
/// not allowed on univariant or zero-variant enums, which have no discriminant.
///
/// If a discriminant type is so specified, then the discriminant will be
/// present (before fields, if any) with that type; representation
/// optimizations which would remove it will not be done.
pub fn find_repr_attr(diagnostic: &SpanHandler, attr: &Attribute, acc: ReprAttr)
-> ReprAttr {
let mut acc = acc;
/// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use
/// the same discriminant size that the corresponding C enum would or C
/// structure layout, and `packed` to remove padding.
pub fn find_repr_attrs(diagnostic: &SpanHandler, attr: &Attribute) -> Vec<ReprAttr> {
let mut acc = Vec::new();
match attr.node.value.node {
ast::MetaList(ref s, ref items) if s.equiv(&("repr")) => {
mark_used(attr);
@ -439,28 +434,26 @@ pub fn find_repr_attr(diagnostic: &SpanHandler, attr: &Attribute, acc: ReprAttr)
ast::MetaWord(ref word) => {
let hint = match word.get() {
// Can't use "extern" because it's not a lexical identifier.
"C" => ReprExtern,
"C" => Some(ReprExtern),
"packed" => Some(ReprPacked),
_ => match int_type_of_word(word.get()) {
Some(ity) => ReprInt(item.span, ity),
Some(ity) => Some(ReprInt(item.span, ity)),
None => {
// Not a word we recognize
diagnostic.span_err(item.span,
"unrecognized representation hint");
ReprAny
None
}
}
};
if hint != ReprAny {
if acc == ReprAny {
acc = hint;
} else if acc != hint {
diagnostic.span_warn(item.span,
"conflicting representation hint ignored")
}
match hint {
Some(h) => acc.push(h),
None => { }
}
}
// Not a word:
_ => diagnostic.span_err(item.span, "unrecognized representation hint")
_ => diagnostic.span_err(item.span, "unrecognized enum representation hint")
}
}
}
@ -490,7 +483,8 @@ fn int_type_of_word(s: &str) -> Option<IntType> {
pub enum ReprAttr {
ReprAny,
ReprInt(Span, IntType),
ReprExtern
ReprExtern,
ReprPacked,
}
impl ReprAttr {
@ -498,7 +492,8 @@ impl ReprAttr {
match *self {
ReprAny => false,
ReprInt(_sp, ity) => ity.is_ffi_safe(),
ReprExtern => true
ReprExtern => true,
ReprPacked => false
}
}
}
@ -523,7 +518,7 @@ impl IntType {
SignedInt(ast::TyI16) | UnsignedInt(ast::TyU16) |
SignedInt(ast::TyI32) | UnsignedInt(ast::TyU32) |
SignedInt(ast::TyI64) | UnsignedInt(ast::TyU64) => true,
_ => false
SignedInt(ast::TyI) | UnsignedInt(ast::TyU) => false
}
}
}

View File

@ -24,7 +24,7 @@ pub mod rustrt {
}
}
pub fn fact(n: uint) -> uint {
pub fn fact(n: libc::uintptr_t) -> libc::uintptr_t {
unsafe {
println!("n = {}", n);
rustrt::rust_dbg_call(cb, n)
@ -32,9 +32,9 @@ pub fn fact(n: uint) -> uint {
}
pub extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
if data == 1u {
if data == 1 {
data
} else {
fact(data - 1u) * data
fact(data - 1) * data
}
}

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[packed]
#[repr(packed)]
pub struct S {
a: u8,
b: u32

View File

@ -0,0 +1,49 @@
// Copyright 2014 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.
#![deny(ctypes)]
#![allow(dead_code)]
struct A {
x: i32
}
#[repr(C, packed)]
struct B {
x: i32,
y: A
}
#[repr(C)]
struct C {
x: i32
}
type A2 = A;
type B2 = B;
type C2 = C;
#[repr(C)]
struct D {
x: C,
y: A
}
extern "C" {
fn foo(x: A); //~ ERROR found type without foreign-function-safe
fn bar(x: B); //~ ERROR foreign-function-safe
fn baz(x: C);
fn qux(x: A2); //~ ERROR foreign-function-safe
fn quux(x: B2); //~ ERROR foreign-function-safe
fn corge(x: C2);
fn fred(x: D); //~ ERROR foreign-function-safe
}
fn main() { }

View File

@ -18,9 +18,9 @@ enum T { E, F, G }
extern {
fn zf(x: Z);
fn uf(x: U);
fn bf(x: B); //~ ERROR found enum type without foreign-function-safe
fn tf(x: T); //~ ERROR found enum type without foreign-function-safe
fn uf(x: U); //~ ERROR found type without foreign-function-safe
fn bf(x: B); //~ ERROR found type without foreign-function-safe
fn tf(x: T); //~ ERROR found type without foreign-function-safe
}
pub fn main() { }

View File

@ -19,7 +19,7 @@ extern crate debug;
use std::mem;
#[packed]
#[repr(packed)]
struct Foo<T,S> {
bar: T,
baz: S

View File

@ -19,7 +19,7 @@ extern crate debug;
use std::mem;
#[packed]
#[repr(packed)]
struct Foo {
bar: u8,
baz: uint

View File

@ -87,7 +87,7 @@ struct PaddedStruct {
e: i16
}
#[packed]
#[repr(packed)]
struct PackedStruct {
a: i16,
b: AnEnum,

View File

@ -77,7 +77,7 @@
#![allow(unused_variable)]
#[packed]
#[repr(packed)]
struct Packed {
x: i16,
y: i32,
@ -88,7 +88,7 @@ impl Drop for Packed {
fn drop(&mut self) {}
}
#[packed]
#[repr(packed)]
struct PackedInPacked {
a: i32,
b: Packed,
@ -113,7 +113,7 @@ impl Drop for Unpacked {
fn drop(&mut self) {}
}
#[packed]
#[repr(packed)]
struct UnpackedInPacked {
a: i16,
b: Unpacked,
@ -121,7 +121,7 @@ struct UnpackedInPacked {
d: i64
}
#[packed]
#[repr(packed)]
struct PackedInPackedWithDrop {
a: i32,
b: Packed,
@ -144,7 +144,7 @@ impl Drop for PackedInUnpackedWithDrop {
fn drop(&mut self) {}
}
#[packed]
#[repr(packed)]
struct UnpackedInPackedWithDrop {
a: i16,
b: Unpacked,

View File

@ -63,14 +63,14 @@
#![allow(unused_variable)]
#[packed]
#[repr(packed)]
struct Packed {
x: i16,
y: i32,
z: i64
}
#[packed]
#[repr(packed)]
struct PackedInPacked {
a: i32,
b: Packed,
@ -95,7 +95,7 @@ struct Unpacked {
}
// layout (64 bit): aabb bbbb bbbb bbbb bbbb bbbb bbcc cccc cccc cccc cccc cccc ccdd dddd dd
#[packed]
#[repr(packed)]
struct UnpackedInPacked {
a: i16,
b: Unpacked,

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[packed]
#[repr(packed)]
#[deriving(PartialEq, Show)]
struct Foo {
a: i8,

View File

@ -22,14 +22,14 @@ mod rustrt {
}
extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
if data == 1u {
if data == 1 {
data
} else {
count(data - 1u) + 1u
count(data - 1) + 1
}
}
fn count(n: uint) -> uint {
fn count(n: libc::uintptr_t) -> libc::uintptr_t {
unsafe {
println!("n = {}", n);
rustrt::rust_dbg_call(cb, n)
@ -37,7 +37,7 @@ fn count(n: uint) -> uint {
}
pub fn main() {
let result = count(1000u);
let result = count(1000);
println!("result = {}", result);
assert_eq!(result, 1000u);
assert_eq!(result, 1000);
}

View File

@ -23,14 +23,14 @@ mod rustrt {
}
extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
if data == 1u {
if data == 1 {
data
} else {
count(data - 1u) + 1u
count(data - 1) + 1
}
}
fn count(n: uint) -> uint {
fn count(n: libc::uintptr_t) -> libc::uintptr_t {
unsafe {
println!("n = {}", n);
rustrt::rust_dbg_call(cb, n)
@ -41,8 +41,8 @@ pub fn main() {
// Make sure we're on a task with small Rust stacks (main currently
// has a large stack)
task::spawn(proc() {
let result = count(1000u);
let result = count(1000);
println!("result = {}", result);
assert_eq!(result, 1000u);
assert_eq!(result, 1000);
});
}

View File

@ -22,14 +22,14 @@ mod rustrt {
}
extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
if data == 1u {
if data == 1 {
data
} else {
fact(data - 1u) * data
fact(data - 1) * data
}
}
fn fact(n: uint) -> uint {
fn fact(n: libc::uintptr_t) -> libc::uintptr_t {
unsafe {
println!("n = {}", n);
rustrt::rust_dbg_call(cb, n)
@ -37,7 +37,7 @@ fn fact(n: uint) -> uint {
}
pub fn main() {
let result = fact(10u);
let result = fact(10);
println!("result = {}", result);
assert_eq!(result, 3628800u);
assert_eq!(result, 3628800);
}

View File

@ -27,14 +27,14 @@ mod rustrt {
}
extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
if data == 1u {
if data == 1 {
data
} else {
count(data - 1u) + count(data - 1u)
count(data - 1) + count(data - 1)
}
}
fn count(n: uint) -> uint {
fn count(n: libc::uintptr_t) -> libc::uintptr_t {
unsafe {
println!("n = {}", n);
rustrt::rust_dbg_call(cb, n)
@ -45,8 +45,8 @@ pub fn main() {
// Make sure we're on a task with small Rust stacks (main currently
// has a large stack)
task::spawn(proc() {
let result = count(12u);
let result = count(12);
println!("result = {}", result);
assert_eq!(result, 2048u);
assert_eq!(result, 2048);
});
}

View File

@ -11,8 +11,9 @@
//aux-build:extern-crosscrate-source.rs
extern crate externcallback;
extern crate libc;
fn fact(n: uint) -> uint {
fn fact(n: libc::uintptr_t) -> libc::uintptr_t {
unsafe {
println!("n = {}", n);
externcallback::rustrt::rust_dbg_call(externcallback::cb, n)
@ -20,7 +21,7 @@ fn fact(n: uint) -> uint {
}
pub fn main() {
let result = fact(10u);
let result = fact(10);
println!("result = {}", result);
assert_eq!(result, 3628800u);
assert_eq!(result, 3628800);
}

View File

@ -26,24 +26,24 @@ mod rustrt {
}
extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
if data == 1u {
if data == 1 {
data
} else {
task::deschedule();
count(data - 1u) + count(data - 1u)
count(data - 1) + count(data - 1)
}
}
fn count(n: uint) -> uint {
fn count(n: libc::uintptr_t) -> libc::uintptr_t {
unsafe {
rustrt::rust_dbg_call(cb, n)
}
}
pub fn main() {
for _ in range(0, 100u) {
for _ in range(0u, 100) {
task::spawn(proc() {
assert_eq!(count(5u), 16u);
assert_eq!(count(5), 16);
});
}
}

View File

@ -23,14 +23,14 @@ mod rustrt {
}
extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
if data == 1u {
if data == 1 {
data
} else {
count(data - 1u) + count(data - 1u)
count(data - 1) + count(data - 1)
}
}
fn count(n: uint) -> uint {
fn count(n: libc::uintptr_t) -> libc::uintptr_t {
unsafe {
task::deschedule();
rustrt::rust_dbg_call(cb, n)
@ -40,9 +40,9 @@ fn count(n: uint) -> uint {
pub fn main() {
for _ in range(0, 10u) {
task::spawn(proc() {
let result = count(5u);
let result = count(5);
println!("result = {}", result);
assert_eq!(result, 16u);
assert_eq!(result, 16);
});
}
}

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[packed]
#[repr(packed)]
struct Foo {
bar: u8,
baz: uint

View File

@ -10,7 +10,7 @@
use std::mem;
#[packed]
#[repr(packed)]
struct S<T, S> {
a: T,
b: u8,

View File

@ -10,7 +10,7 @@
use std::mem;
#[packed]
#[repr(packed)]
struct S<T, S> {
a: T,
b: u8,

View File

@ -10,13 +10,13 @@
use std::mem;
#[packed]
#[repr(packed)]
struct S4 {
a: u8,
b: [u8, .. 3],
}
#[packed]
#[repr(packed)]
struct S5 {
a: u8,
b: u32

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[packed]
#[repr(packed)]
struct Foo {
bar: u8,
baz: uint

View File

@ -12,19 +12,19 @@
use std::mem;
use std::gc::Gc;
#[packed]
#[repr(packed)]
struct S4 {
a: u8,
b: [u8, .. 3],
}
#[packed]
#[repr(packed)]
struct S5 {
a: u8,
b: u32
}
#[packed]
#[repr(packed)]
struct S13 {
a: i64,
b: f32,
@ -36,14 +36,14 @@ enum Foo {
Baz = 2
}
#[packed]
#[repr(packed)]
struct S3_Foo {
a: u8,
b: u16,
c: Foo
}
#[packed]
#[repr(packed)]
struct S7_Option {
a: f32,
b: u8,

View File

@ -12,7 +12,7 @@
use std::mem;
#[packed]
#[repr(packed)]
#[deriving(PartialEq, Show)]
struct Foo {
bar: u8,

View File

@ -10,10 +10,10 @@
use std::mem;
#[packed]
#[repr(packed)]
struct S4(u8,[u8, .. 3]);
#[packed]
#[repr(packed)]
struct S5(u8,u32);
pub fn main() {

View File

@ -12,13 +12,13 @@
use std::gc::Gc;
use std::mem;
#[packed]
#[repr(packed)]
struct S4(u8,[u8, .. 3]);
#[packed]
#[repr(packed)]
struct S5(u8, u32);
#[packed]
#[repr(packed)]
struct S13(i64, f32, u8);
enum Foo {
@ -26,10 +26,10 @@ enum Foo {
Baz = 2
}
#[packed]
#[repr(packed)]
struct S3_Foo(u8, u16, Foo);
#[packed]
#[repr(packed)]
struct S7_Option(f32, u8, u16, Option<Gc<f64>>);
pub fn main() {