Skip to content

Commit 5e1a691

Browse files
committed
auto merge of rust-lang#9613 : jld/rust/enum-discrim-size.r0, r=alexcrichton
Allows an enum with a discriminant to use any of the primitive integer types to store it. By default the smallest usable type is chosen, but this can be overridden with an attribute: `#[repr(int)]` etc., or `#[repr(C)]` to match the target's C ABI for the equivalent C enum. Also adds a lint pass for using non-FFI safe enums in extern declarations, checks that specified discriminants can be stored in the specified type if any, and fixes assorted code that was assuming int.
2 parents e42e378 + 86a710e commit 5e1a691

32 files changed

+967
-198
lines changed

mk/tests.mk

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,17 @@ $(foreach host,$(CFG_HOST_TRIPLES), \
465465
$(eval $(call DEF_TEST_CRATE_RULES,$(stage),$(target),$(host),$(crate))) \
466466
))))))
467467

468+
# FIXME (#10104): Raise the stack size to work around rustpkg bypassing
469+
# the code in rustc that would take care of it.
470+
define DEF_RUSTPKG_STACK_FIX
471+
$$(call TEST_OK_FILE,$(1),$(2),$(3),rustpkg): export RUST_MIN_STACK=8000000
472+
endef
473+
474+
$(foreach host,$(CFG_HOST_TRIPLES), \
475+
$(foreach target,$(CFG_TARGET_TRIPLES), \
476+
$(foreach stage,$(STAGES), \
477+
$(eval $(call DEF_RUSTPKG_STACK_FIX,$(stage),$(target),$(host))))))
478+
468479

469480
######################################################################
470481
# Rules for the compiletest tests (rpass, rfail, etc.)

src/compiletest/runtest.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
281281
};
282282
let config = &mut config;
283283
let cmds = props.debugger_cmds.connect("\n");
284-
let check_lines = props.check_lines.clone();
284+
let check_lines = &props.check_lines;
285285

286286
// compile test file (it shoud have 'compile-flags:-g' in the header)
287287
let mut ProcRes = compile_test(config, props, testfile);
@@ -315,11 +315,34 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
315315

316316
let num_check_lines = check_lines.len();
317317
if num_check_lines > 0 {
318+
// Allow check lines to leave parts unspecified (e.g., uninitialized
319+
// bits in the wrong case of an enum) with the notation "[...]".
320+
let check_fragments: ~[~[&str]] = check_lines.map(|s| s.split_str_iter("[...]").collect());
318321
// check if each line in props.check_lines appears in the
319322
// output (in order)
320323
let mut i = 0u;
321324
for line in ProcRes.stdout.line_iter() {
322-
if check_lines[i].trim() == line.trim() {
325+
let mut rest = line.trim();
326+
let mut first = true;
327+
let mut failed = false;
328+
for &frag in check_fragments[i].iter() {
329+
let found = if first {
330+
if rest.starts_with(frag) { Some(0) } else { None }
331+
} else {
332+
rest.find_str(frag)
333+
};
334+
match found {
335+
None => {
336+
failed = true;
337+
break;
338+
}
339+
Some(i) => {
340+
rest = rest.slice_from(i + frag.len());
341+
}
342+
}
343+
first = false;
344+
}
345+
if !failed && rest.len() == 0 {
323346
i += 1u;
324347
}
325348
if i == num_check_lines {

src/libextra/enum_set.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ mod test {
140140
use enum_set::*;
141141

142142
#[deriving(Eq)]
143+
#[repr(uint)]
143144
enum Foo {
144145
A, B, C
145146
}

src/librustc/lib/llvm.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ pub static Vector: TypeKind = 13;
147147
pub static Metadata: TypeKind = 14;
148148
pub static X86_MMX: TypeKind = 15;
149149

150+
#[repr(C)]
150151
pub enum AtomicBinOp {
151152
Xchg = 0,
152153
Add = 1,
@@ -161,6 +162,7 @@ pub enum AtomicBinOp {
161162
UMin = 10,
162163
}
163164

165+
#[repr(C)]
164166
pub enum AtomicOrdering {
165167
NotAtomic = 0,
166168
Unordered = 1,
@@ -173,6 +175,7 @@ pub enum AtomicOrdering {
173175
}
174176

175177
// Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h)
178+
#[repr(C)]
176179
pub enum FileType {
177180
AssemblyFile = 0,
178181
ObjectFile = 1
@@ -194,20 +197,23 @@ pub enum AsmDialect {
194197
}
195198

196199
#[deriving(Eq)]
200+
#[repr(C)]
197201
pub enum CodeGenOptLevel {
198202
CodeGenLevelNone = 0,
199203
CodeGenLevelLess = 1,
200204
CodeGenLevelDefault = 2,
201205
CodeGenLevelAggressive = 3,
202206
}
203207

208+
#[repr(C)]
204209
pub enum RelocMode {
205210
RelocDefault = 0,
206211
RelocStatic = 1,
207212
RelocPIC = 2,
208213
RelocDynamicNoPic = 3,
209214
}
210215

216+
#[repr(C)]
211217
pub enum CodeGenModel {
212218
CodeModelDefault = 0,
213219
CodeModelJITDefault = 1,

src/librustc/metadata/common.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ pub static tag_items_data_item_reexport_name: uint = 0x4f;
112112

113113
// used to encode crate_ctxt side tables
114114
#[deriving(Eq)]
115+
#[repr(uint)]
115116
pub enum astencode_tag { // Reserves 0x50 -- 0x6f
116117
tag_ast = 0x50,
117118

@@ -143,7 +144,7 @@ impl astencode_tag {
143144
pub fn from_uint(value : uint) -> Option<astencode_tag> {
144145
let is_a_tag = first_astencode_tag <= value && value <= last_astencode_tag;
145146
if !is_a_tag { None } else {
146-
Some(unsafe { cast::transmute(value as int) })
147+
Some(unsafe { cast::transmute(value) })
147148
}
148149
}
149150
}

src/librustc/metadata/encoder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
989989
encode_family(ebml_w, 't');
990990
encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
991991
encode_name(ecx, ebml_w, item.ident);
992+
encode_attributes(ebml_w, item.attrs);
992993
for v in (*enum_definition).variants.iter() {
993994
encode_variant_id(ebml_w, local_def(v.node.id));
994995
}

src/librustc/middle/lint.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
//! Context itself, span_lint should be used instead of add_lint.
3535
3636
use driver::session;
37+
use middle::trans::adt; // for `adt::is_ffi_safe`
3738
use middle::ty;
3839
use middle::pat_util;
3940
use metadata::csearch;
@@ -627,6 +628,14 @@ fn check_item_ctypes(cx: &Context, it: &ast::item) {
627628
"found rust type `uint` in foreign module, while \
628629
libc::c_uint or libc::c_ulong should be used");
629630
}
631+
ast::DefTy(def_id) => {
632+
if !adt::is_ffi_safe(cx.tcx, def_id) {
633+
cx.span_lint(ctypes, ty.span,
634+
"found enum type without foreign-function-safe \
635+
representation annotation in foreign module");
636+
// NOTE this message could be more helpful
637+
}
638+
}
630639
_ => ()
631640
}
632641
}

0 commit comments

Comments
 (0)