diff --git a/src/doc/guide-ffi.md b/src/doc/guide-ffi.md index 600a9019e6b..0ded9db3ad0 100644 --- a/src/doc/guide-ffi.md +++ b/src/doc/guide-ffi.md @@ -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`) 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 diff --git a/src/doc/rust.md b/src/doc/rust.md index 206ec787d5e..4bbcba6c2f3 100644 --- a/src/doc/rust.md +++ b/src/doc/rust.md @@ -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. diff --git a/src/libcore/simd.rs b/src/libcore/simd.rs index 54e7d077bb1..42418ccbc1a 100644 --- a/src/libcore/simd.rs +++ b/src/libcore/simd.rs @@ -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); diff --git a/src/libgreen/context.rs b/src/libgreen/context.rs index b63758cdcc5..64537ea12d9 100644 --- a/src/libgreen/context.rs +++ b/src/libgreen/context.rs @@ -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 { #[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 { 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 { diff --git a/src/libgreen/stack.rs b/src/libgreen/stack.rs index 601758f8a25..4673e7b3ba2 100644 --- a/src/libgreen/stack.rs +++ b/src/libgreen/stack.rs @@ -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; } diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 9c699a88007..859a2bce972 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -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 int>, + errno: c_int) -> int>, pglob: *mut glob_t); pub fn globfree(pglob: *mut glob_t); } diff --git a/src/libnative/io/c_unix.rs b/src/libnative/io/c_unix.rs index af4d309dfe2..fa7da1de914 100644 --- a/src/libnative/io/c_unix.rs +++ b/src/libnative/io/c_unix.rs @@ -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, diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 7e0ba613e3d..80b47640146 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -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); diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 9a7bfb0e6dc..0dfdf455743 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -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, diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 9c68631baa4..483937edd9f 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -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> 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() { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index f9043ca337f..2b768c811e7 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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, @@ -3968,7 +4031,7 @@ pub fn substd_enum_variants(cx: &ctxt, -> Vec> { 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::>(); 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 { + 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 diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index f33406be595..ea17691d17d 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -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, diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 97fa58d5077..305c18480f6 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -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, } +#[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, } +#[repr(C)] struct hoedown_buffer { data: *const u8, size: libc::size_t, diff --git a/src/librustrt/libunwind.rs b/src/librustrt/libunwind.rs index 72d78d84aa3..8d2305a8a80 100644 --- a/src/librustrt/libunwind.rs +++ b/src/librustrt/libunwind.rs @@ -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, diff --git a/src/librustuv/uvll.rs b/src/librustuv/uvll.rs index b06065659bd..e7b031c6b51 100644 --- a/src/librustuv/uvll.rs +++ b/src/librustuv/uvll.rs @@ -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()); } } diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs index 079a9aef648..769ad2a8468 100644 --- a/src/libstd/io/test.rs +++ b/src/libstd/io/test.rs @@ -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 diff --git a/src/libstd/os.rs b/src/libstd/os.rs index d8eb0979190..7780c61e866 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -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 { diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index a4491b2ab1d..1b005f49b88 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -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, diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 21252619d11..4b2a3073755 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -418,19 +418,14 @@ pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[Gc]) { } -/// 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 { + 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 { 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 } } } diff --git a/src/test/auxiliary/extern-crosscrate-source.rs b/src/test/auxiliary/extern-crosscrate-source.rs index 5c83b327912..0e3b531e458 100644 --- a/src/test/auxiliary/extern-crosscrate-source.rs +++ b/src/test/auxiliary/extern-crosscrate-source.rs @@ -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 } } diff --git a/src/test/auxiliary/packed.rs b/src/test/auxiliary/packed.rs index 54b2658e380..86f5f93e3cf 100644 --- a/src/test/auxiliary/packed.rs +++ b/src/test/auxiliary/packed.rs @@ -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 diff --git a/src/test/compile-fail/issue-14309.rs b/src/test/compile-fail/issue-14309.rs new file mode 100644 index 00000000000..d4a40ade72c --- /dev/null +++ b/src/test/compile-fail/issue-14309.rs @@ -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 or the MIT license +// , 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() { } diff --git a/src/test/compile-fail/lint-ctypes-enum.rs b/src/test/compile-fail/lint-ctypes-enum.rs index e968bd601c5..d45a3b027a7 100644 --- a/src/test/compile-fail/lint-ctypes-enum.rs +++ b/src/test/compile-fail/lint-ctypes-enum.rs @@ -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() { } diff --git a/src/test/compile-fail/packed-struct-generic-transmute.rs b/src/test/compile-fail/packed-struct-generic-transmute.rs index b5bb3314dcf..7a1ff574488 100644 --- a/src/test/compile-fail/packed-struct-generic-transmute.rs +++ b/src/test/compile-fail/packed-struct-generic-transmute.rs @@ -19,7 +19,7 @@ extern crate debug; use std::mem; -#[packed] +#[repr(packed)] struct Foo { bar: T, baz: S diff --git a/src/test/compile-fail/packed-struct-transmute.rs b/src/test/compile-fail/packed-struct-transmute.rs index 0611c470d10..f92cc4b1344 100644 --- a/src/test/compile-fail/packed-struct-transmute.rs +++ b/src/test/compile-fail/packed-struct-transmute.rs @@ -19,7 +19,7 @@ extern crate debug; use std::mem; -#[packed] +#[repr(packed)] struct Foo { bar: u8, baz: uint diff --git a/src/test/debuginfo/c-style-enum-in-composite.rs b/src/test/debuginfo/c-style-enum-in-composite.rs index f7351728290..ef23e7ee876 100644 --- a/src/test/debuginfo/c-style-enum-in-composite.rs +++ b/src/test/debuginfo/c-style-enum-in-composite.rs @@ -87,7 +87,7 @@ struct PaddedStruct { e: i16 } -#[packed] +#[repr(packed)] struct PackedStruct { a: i16, b: AnEnum, diff --git a/src/test/debuginfo/packed-struct-with-destructor.rs b/src/test/debuginfo/packed-struct-with-destructor.rs index 215d961b71b..00a560edbf0 100644 --- a/src/test/debuginfo/packed-struct-with-destructor.rs +++ b/src/test/debuginfo/packed-struct-with-destructor.rs @@ -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, diff --git a/src/test/debuginfo/packed-struct.rs b/src/test/debuginfo/packed-struct.rs index 8201afe3a01..bf2213509cf 100644 --- a/src/test/debuginfo/packed-struct.rs +++ b/src/test/debuginfo/packed-struct.rs @@ -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, diff --git a/src/test/run-make/extern-fn-with-packed-struct/test.rs b/src/test/run-make/extern-fn-with-packed-struct/test.rs index 4b07b7f39f5..8d8daed1393 100644 --- a/src/test/run-make/extern-fn-with-packed-struct/test.rs +++ b/src/test/run-make/extern-fn-with-packed-struct/test.rs @@ -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, diff --git a/src/test/run-pass/extern-call-deep.rs b/src/test/run-pass/extern-call-deep.rs index d05057ea251..93a5752d004 100644 --- a/src/test/run-pass/extern-call-deep.rs +++ b/src/test/run-pass/extern-call-deep.rs @@ -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); } diff --git a/src/test/run-pass/extern-call-deep2.rs b/src/test/run-pass/extern-call-deep2.rs index 654541dcde0..bc5ccc30c52 100644 --- a/src/test/run-pass/extern-call-deep2.rs +++ b/src/test/run-pass/extern-call-deep2.rs @@ -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); }); } diff --git a/src/test/run-pass/extern-call-indirect.rs b/src/test/run-pass/extern-call-indirect.rs index 8db745424b2..52697d96b32 100644 --- a/src/test/run-pass/extern-call-indirect.rs +++ b/src/test/run-pass/extern-call-indirect.rs @@ -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); } diff --git a/src/test/run-pass/extern-call-scrub.rs b/src/test/run-pass/extern-call-scrub.rs index 07d425dcdad..ae9430370d5 100644 --- a/src/test/run-pass/extern-call-scrub.rs +++ b/src/test/run-pass/extern-call-scrub.rs @@ -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); }); } diff --git a/src/test/run-pass/extern-crosscrate.rs b/src/test/run-pass/extern-crosscrate.rs index 5dc25c85325..18e20332adc 100644 --- a/src/test/run-pass/extern-crosscrate.rs +++ b/src/test/run-pass/extern-crosscrate.rs @@ -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); } diff --git a/src/test/run-pass/extern-stress.rs b/src/test/run-pass/extern-stress.rs index 18e771b9b1e..87d96880e4b 100644 --- a/src/test/run-pass/extern-stress.rs +++ b/src/test/run-pass/extern-stress.rs @@ -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); }); } } diff --git a/src/test/run-pass/extern-yield.rs b/src/test/run-pass/extern-yield.rs index 0735cca1864..7fb68e9f8a0 100644 --- a/src/test/run-pass/extern-yield.rs +++ b/src/test/run-pass/extern-yield.rs @@ -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); }); } } diff --git a/src/test/run-pass/packed-struct-borrow-element.rs b/src/test/run-pass/packed-struct-borrow-element.rs index 1434e1da4c7..c6c74fe3fda 100644 --- a/src/test/run-pass/packed-struct-borrow-element.rs +++ b/src/test/run-pass/packed-struct-borrow-element.rs @@ -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 diff --git a/src/test/run-pass/packed-struct-generic-layout.rs b/src/test/run-pass/packed-struct-generic-layout.rs index 20269766158..999e4aeeb59 100644 --- a/src/test/run-pass/packed-struct-generic-layout.rs +++ b/src/test/run-pass/packed-struct-generic-layout.rs @@ -10,7 +10,7 @@ use std::mem; -#[packed] +#[repr(packed)] struct S { a: T, b: u8, diff --git a/src/test/run-pass/packed-struct-generic-size.rs b/src/test/run-pass/packed-struct-generic-size.rs index 80f37a0fa3d..45791332bbe 100644 --- a/src/test/run-pass/packed-struct-generic-size.rs +++ b/src/test/run-pass/packed-struct-generic-size.rs @@ -10,7 +10,7 @@ use std::mem; -#[packed] +#[repr(packed)] struct S { a: T, b: u8, diff --git a/src/test/run-pass/packed-struct-layout.rs b/src/test/run-pass/packed-struct-layout.rs index 7f9bf8e7d57..b4fbf0820cd 100644 --- a/src/test/run-pass/packed-struct-layout.rs +++ b/src/test/run-pass/packed-struct-layout.rs @@ -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 diff --git a/src/test/run-pass/packed-struct-match.rs b/src/test/run-pass/packed-struct-match.rs index 27ab2c83e55..46ffed0cba9 100644 --- a/src/test/run-pass/packed-struct-match.rs +++ b/src/test/run-pass/packed-struct-match.rs @@ -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 diff --git a/src/test/run-pass/packed-struct-size.rs b/src/test/run-pass/packed-struct-size.rs index 8dbc7cf327d..cfea444d7ff 100644 --- a/src/test/run-pass/packed-struct-size.rs +++ b/src/test/run-pass/packed-struct-size.rs @@ -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, diff --git a/src/test/run-pass/packed-struct-vec.rs b/src/test/run-pass/packed-struct-vec.rs index 8309e95820c..c20e62351a6 100644 --- a/src/test/run-pass/packed-struct-vec.rs +++ b/src/test/run-pass/packed-struct-vec.rs @@ -12,7 +12,7 @@ use std::mem; -#[packed] +#[repr(packed)] #[deriving(PartialEq, Show)] struct Foo { bar: u8, diff --git a/src/test/run-pass/packed-tuple-struct-layout.rs b/src/test/run-pass/packed-tuple-struct-layout.rs index 3ec6182beb2..5fb43503ccb 100644 --- a/src/test/run-pass/packed-tuple-struct-layout.rs +++ b/src/test/run-pass/packed-tuple-struct-layout.rs @@ -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() { diff --git a/src/test/run-pass/packed-tuple-struct-size.rs b/src/test/run-pass/packed-tuple-struct-size.rs index da6e9a9dac0..f23166288fb 100644 --- a/src/test/run-pass/packed-tuple-struct-size.rs +++ b/src/test/run-pass/packed-tuple-struct-size.rs @@ -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>); pub fn main() {