mirror of
https://github.com/rust-lang/rust
synced 2024-09-15 22:50:55 +00:00
librustc: handle repr on structs, require it for ffi, unify with packed
As of RFC 18, struct layout is undefined. Opting into a C-compatible struct layout is now down with #[repr(C)]. For consistency, specifying a packed layout is now also down with #[repr(packed)]. Both can be specified. To fix errors caused by this, just add #[repr(C)] to the structs, and change #[packed] to #[repr(packed)] Closes #14309 [breaking-change]
This commit is contained in:
parent
54bd9e6323
commit
6e8ff99958
|
@ -334,6 +334,7 @@ pub enum c_void {
|
|||
__variant1,
|
||||
__variant2,
|
||||
}
|
||||
|
||||
pub enum FILE {}
|
||||
pub enum fpos_t {}
|
||||
}
|
||||
|
|
|
@ -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,8 +361,13 @@ fn check_ty(cx: &Context, ty: &ast::Ty) {
|
|||
"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
|
||||
representation annotation in foreign module, consider \
|
||||
|
@ -770,9 +774,10 @@ fn check_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ fn check_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
|
|||
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);
|
||||
|
|
|
@ -195,9 +195,10 @@ fn visit_node(&mut self, node: &ast_map::Node) {
|
|||
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,
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -481,7 +481,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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1962,7 +1962,8 @@ mod TC {
|
|||
// 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,
|
||||
|
@ -2199,6 +2200,11 @@ fn tc_ty(cx: &ctxt,
|
|||
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 => {
|
||||
|
@ -2206,22 +2212,22 @@ fn tc_ty(cx: &ctxt,
|
|||
}
|
||||
|
||||
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) => {
|
||||
|
@ -2229,8 +2235,9 @@ fn tc_ty(cx: &ctxt,
|
|||
}
|
||||
|
||||
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)),
|
||||
}
|
||||
}
|
||||
|
@ -2244,6 +2251,11 @@ fn tc_ty(cx: &ctxt,
|
|||
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;
|
||||
}
|
||||
|
@ -2273,9 +2285,49 @@ fn tc_ty(cx: &ctxt,
|
|||
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)
|
||||
}
|
||||
|
||||
|
@ -2427,6 +2479,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>,
|
||||
|
@ -3945,7 +4001,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);
|
||||
|
||||
|
@ -4168,9 +4224,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]`
|
||||
|
@ -4178,14 +4234,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
|
||||
|
|
|
@ -4180,13 +4180,13 @@ fn do_check(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
|
||||
|
@ -4225,6 +4225,9 @@ fn do_check(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);
|
||||
|
||||
|
@ -4238,7 +4241,9 @@ fn do_check(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,
|
||||
|
|
|
@ -72,6 +72,7 @@ pub enum _Unwind_Reason_Code {
|
|||
#[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,
|
||||
|
|
|
@ -701,7 +701,7 @@ mod imp {
|
|||
static IMAGE_FILE_MACHINE_IA64: libc::DWORD = 0x0200;
|
||||
static IMAGE_FILE_MACHINE_AMD64: libc::DWORD = 0x8664;
|
||||
|
||||
#[packed]
|
||||
#[repr(packed)]
|
||||
struct SYMBOL_INFO {
|
||||
SizeOfStruct: libc::c_ulong,
|
||||
TypeIndex: libc::c_ulong,
|
||||
|
|
|
@ -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 @@ pub fn is_ffi_safe(&self) -> bool {
|
|||
match *self {
|
||||
ReprAny => false,
|
||||
ReprInt(_sp, ity) => ity.is_ffi_safe(),
|
||||
ReprExtern => true
|
||||
ReprExtern => true,
|
||||
ReprPacked => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -523,7 +518,7 @@ fn is_ffi_safe(self) -> bool {
|
|||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
49
src/test/compile-fail/issue-14309.rs
Normal file
49
src/test/compile-fail/issue-14309.rs
Normal 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 { //~ NOTE consider adding `#[repr(C)]` to this type
|
||||
x: int
|
||||
}
|
||||
|
||||
#[repr(C, packed)]
|
||||
struct B {
|
||||
x: int,
|
||||
y: A
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct C {
|
||||
x: int
|
||||
}
|
||||
|
||||
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 struct without FFI-safe representation used in FFI
|
||||
fn bar(x: B); //~ ERROR FFI-safe
|
||||
fn baz(x: C);
|
||||
fn qux(x: A2); //~ ERROR FFI-safe
|
||||
fn quux(x: B2); //~ ERROR FFI-safe
|
||||
fn corge(x: C2);
|
||||
fn fred(x: D); //~ ERROR FFI-safe
|
||||
}
|
||||
|
||||
fn main() { }
|
|
@ -19,8 +19,8 @@ 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 bf(x: B); //~ ERROR found enum without FFI-safe
|
||||
fn tf(x: T); //~ ERROR found enum without FFI-safe
|
||||
}
|
||||
|
||||
pub fn main() { }
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
use std::mem;
|
||||
|
||||
#[packed]
|
||||
#[repr(packed)]
|
||||
struct Foo<T,S> {
|
||||
bar: T,
|
||||
baz: S
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
use std::mem;
|
||||
|
||||
#[packed]
|
||||
#[repr(packed)]
|
||||
struct Foo {
|
||||
bar: u8,
|
||||
baz: uint
|
||||
|
|
|
@ -87,7 +87,7 @@ struct PaddedStruct {
|
|||
e: i16
|
||||
}
|
||||
|
||||
#[packed]
|
||||
#[repr(packed)]
|
||||
struct PackedStruct {
|
||||
a: i16,
|
||||
b: AnEnum,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use std::mem;
|
||||
|
||||
#[packed]
|
||||
#[repr(packed)]
|
||||
struct S<T, S> {
|
||||
a: T,
|
||||
b: u8,
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use std::mem;
|
||||
|
||||
#[packed]
|
||||
#[repr(packed)]
|
||||
struct S<T, S> {
|
||||
a: T,
|
||||
b: u8,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
use std::mem;
|
||||
|
||||
#[packed]
|
||||
#[repr(packed)]
|
||||
#[deriving(PartialEq, Show)]
|
||||
struct Foo {
|
||||
bar: u8,
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in a new issue