debuginfo: Support for tuple-style enums (WIP)
This commit is contained in:
parent
739f3eece9
commit
f389bd8f2a
6 changed files with 268 additions and 97 deletions
|
@ -2115,7 +2115,21 @@ pub mod llvm {
|
|||
AlignInBits: c_ulonglong,
|
||||
Elements: ValueRef,
|
||||
ClassType: ValueRef) -> ValueRef;
|
||||
}}
|
||||
|
||||
#[fast_ffi]
|
||||
pub unsafe fn LLVMDIBuilderCreateUnionType(
|
||||
Builder: DIBuilderRef,
|
||||
Scope: ValueRef,
|
||||
Name: *c_char,
|
||||
File: ValueRef,
|
||||
LineNumber: c_uint,
|
||||
SizeInBits: c_ulonglong,
|
||||
AlignInBits: c_ulonglong,
|
||||
Flags: c_uint ,
|
||||
Elements: ValueRef,
|
||||
RunTimeLang : c_uint) -> ValueRef;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn SetInstructionCallConv(Instr: ValueRef, CC: CallConv) {
|
||||
unsafe {
|
||||
|
|
|
@ -501,9 +501,9 @@ fn create_struct(cx: &mut CrateContext,
|
|||
fields: ~[ty::field],
|
||||
span: span)
|
||||
-> DICompositeType {
|
||||
debug!("create_struct: %?", ty::get(struct_type));
|
||||
|
||||
let struct_name = ty_to_str(cx.tcx, struct_type);
|
||||
debug!("create_struct: %s", struct_name);
|
||||
|
||||
let struct_llvm_type = type_of::type_of(cx, struct_type);
|
||||
|
||||
let field_llvm_types = fields.map(|field| type_of::type_of(cx, field.mt.ty));
|
||||
|
@ -526,7 +526,7 @@ fn create_tuple(cx: &mut CrateContext,
|
|||
span: span)
|
||||
-> DICompositeType {
|
||||
|
||||
let tuple_name = "tuple"; // this should have a better name
|
||||
let tuple_name = ty_to_str(cx.tcx, tuple_type);
|
||||
let tuple_llvm_type = type_of::type_of(cx, tuple_type);
|
||||
// Create a vec of empty strings. A vec::build_n() function would be nice for this.
|
||||
let mut component_names : ~[~str] = vec::with_capacity(component_types.len());
|
||||
|
@ -548,63 +548,119 @@ fn create_tuple(cx: &mut CrateContext,
|
|||
fn create_enum_md(cx: &mut CrateContext,
|
||||
enum_type: ty::t,
|
||||
enum_def_id: ast::def_id,
|
||||
span: span) -> DIType {
|
||||
substs: &ty::substs,
|
||||
span: span)
|
||||
-> DIType {
|
||||
|
||||
let enum_name = ty_to_str(cx.tcx, enum_type);
|
||||
let discriminator_llvm_type = Type::enum_discrim(cx);
|
||||
let discriminator_size = machine::llsize_of_alloc(cx, discriminator_llvm_type);
|
||||
let discriminator_align = machine::llalign_of_min(cx, discriminator_llvm_type);
|
||||
|
||||
assert!(Type::enum_discrim(cx) == cx.int_type);
|
||||
let discriminator_type_md = get_or_create_type(cx, ty::mk_int(), span);
|
||||
|
||||
// For empty enums there is an early exit. Just describe it as an empty struct with the
|
||||
// appropriate name
|
||||
if ty::type_is_empty(cx.tcx, enum_type) {
|
||||
// XXX: This should not "rename" the type to nil
|
||||
return get_or_create_type(cx, ty::mk_nil(), span);
|
||||
return create_composite_type(cx, Type::nil(), enum_name, &[], &[], &[], span);
|
||||
}
|
||||
|
||||
// Prepare some data (llvm type, size, align, ...) about the discriminant. This data will be
|
||||
// needed in all of the following cases.
|
||||
let discriminant_llvm_type = Type::enum_discrim(cx);
|
||||
let discriminant_size = machine::llsize_of_alloc(cx, discriminant_llvm_type);
|
||||
let discriminant_align = machine::llalign_of_min(cx, discriminant_llvm_type);
|
||||
assert!(Type::enum_discrim(cx) == cx.int_type);
|
||||
let discriminant_type_md = get_or_create_type(cx, ty::mk_int(), span);
|
||||
|
||||
|
||||
let variants : &[ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id);
|
||||
|
||||
let enumerators : ~[(~str, int)] = variants
|
||||
.iter()
|
||||
.transform(|v| (cx.sess.str_of(v.name).to_owned(), v.disr_val))
|
||||
.collect();
|
||||
|
||||
let enumerators_md : ~[DIDescriptor] =
|
||||
do enumerators.iter().transform |&(name,value)| {
|
||||
do name.as_c_str |name| { unsafe {
|
||||
llvm::LLVMDIBuilderCreateEnumerator(
|
||||
DIB(cx),
|
||||
name,
|
||||
value as c_ulonglong)
|
||||
}}
|
||||
}.collect();
|
||||
|
||||
let loc = span_start(cx, span);
|
||||
let file_metadata = get_or_create_file(cx, loc.file.name);
|
||||
|
||||
let discriminant_type_md = do enum_name.as_c_str |enum_name| { unsafe {
|
||||
llvm::LLVMDIBuilderCreateEnumerationType(
|
||||
DIB(cx),
|
||||
file_metadata,
|
||||
enum_name,
|
||||
file_metadata,
|
||||
loc.line as c_uint,
|
||||
bytes_to_bits(discriminant_size),
|
||||
bytes_to_bits(discriminant_align),
|
||||
create_DIArray(DIB(cx), enumerators_md),
|
||||
discriminant_type_md)
|
||||
}};
|
||||
|
||||
if ty::type_is_c_like_enum(cx.tcx, enum_type) {
|
||||
|
||||
let variants : &[ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id);
|
||||
|
||||
let enumerators : ~[(~str, int)] = variants
|
||||
.iter()
|
||||
.transform(|v| (cx.sess.str_of(v.name).to_owned(), v.disr_val))
|
||||
.collect();
|
||||
|
||||
let enumerators_md : ~[DIDescriptor] =
|
||||
do enumerators.iter().transform |&(name,value)| {
|
||||
do name.as_c_str |name| { unsafe {
|
||||
llvm::LLVMDIBuilderCreateEnumerator(
|
||||
DIB(cx),
|
||||
name,
|
||||
value as c_ulonglong)
|
||||
}}
|
||||
}.collect();
|
||||
|
||||
let loc = span_start(cx, span);
|
||||
let file_metadata = get_or_create_file(cx, loc.file.name);
|
||||
|
||||
return do enum_name.as_c_str |enum_name| { unsafe {
|
||||
llvm::LLVMDIBuilderCreateEnumerationType(
|
||||
DIB(cx),
|
||||
file_metadata,
|
||||
enum_name,
|
||||
file_metadata,
|
||||
loc.line as c_uint,
|
||||
bytes_to_bits(discriminator_size),
|
||||
bytes_to_bits(discriminator_align),
|
||||
create_DIArray(DIB(cx), enumerators_md),
|
||||
discriminator_type_md)
|
||||
}};
|
||||
return discriminant_type_md;
|
||||
}
|
||||
|
||||
cx.sess.bug("");
|
||||
let variants_md = do variants.map |&vi| {
|
||||
|
||||
let raw_types : &[ty::t] = vi.args;
|
||||
let arg_types = do raw_types.map |&raw_type| { ty::subst(cx.tcx, substs, raw_type) };
|
||||
let arg_llvm_types = ~[discriminant_llvm_type] + do arg_types.map |&ty| { type_of::type_of(cx, ty) };
|
||||
let arg_names = ~[~""] + arg_types.map(|_| ~"");
|
||||
let arg_md = ~[discriminant_type_md] + do arg_types.map |&ty| { get_or_create_type(cx, ty, span) };
|
||||
|
||||
let variant_llvm_type = Type::struct_(arg_llvm_types, false);
|
||||
let variant_type_size = machine::llsize_of_alloc(cx, variant_llvm_type);
|
||||
let variant_type_align = machine::llalign_of_min(cx, variant_llvm_type);
|
||||
|
||||
let variant_type_md = create_composite_type(
|
||||
cx,
|
||||
variant_llvm_type,
|
||||
&"",
|
||||
arg_llvm_types,
|
||||
arg_names,
|
||||
arg_md,
|
||||
span);
|
||||
|
||||
do "".as_c_str |name| { unsafe {
|
||||
llvm::LLVMDIBuilderCreateMemberType(
|
||||
DIB(cx),
|
||||
file_metadata,
|
||||
name,
|
||||
file_metadata,
|
||||
loc.line as c_uint,
|
||||
bytes_to_bits(variant_type_size),
|
||||
bytes_to_bits(variant_type_align),
|
||||
bytes_to_bits(0),
|
||||
0,
|
||||
variant_type_md)
|
||||
}}
|
||||
};
|
||||
|
||||
let enum_llvm_type = type_of::type_of(cx, enum_type);
|
||||
let enum_type_size = machine::llsize_of_alloc(cx, enum_llvm_type);
|
||||
let enum_type_align = machine::llalign_of_min(cx, enum_llvm_type);
|
||||
|
||||
return do "".as_c_str |enum_name| { unsafe { llvm::LLVMDIBuilderCreateUnionType(
|
||||
DIB(cx),
|
||||
file_metadata,
|
||||
enum_name,
|
||||
file_metadata,
|
||||
loc.line as c_uint,
|
||||
bytes_to_bits(enum_type_size),
|
||||
bytes_to_bits(enum_type_align),
|
||||
0, // Flags
|
||||
create_DIArray(DIB(cx), variants_md),
|
||||
0) // RuntimeLang
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
|
||||
///
|
||||
/// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
|
||||
|
@ -899,10 +955,8 @@ fn get_or_create_type(cx: &mut CrateContext, t: ty::t, span: span) -> DIType {
|
|||
}
|
||||
}
|
||||
},
|
||||
ty::ty_enum(def_id, ref _substs) => {
|
||||
//cx.sess.span_note(span, "debuginfo for enum NYI");
|
||||
//create_unimpl_ty(cx, t)
|
||||
create_enum_md(cx, t, def_id, span)
|
||||
ty::ty_enum(def_id, ref substs) => {
|
||||
create_enum_md(cx, t, def_id, substs, span)
|
||||
},
|
||||
ty::ty_box(ref mt) |
|
||||
ty::ty_uniq(ref mt) => {
|
||||
|
|
|
@ -565,8 +565,8 @@ extern "C" bool LLVMRustStartMultithreading() {
|
|||
typedef DIBuilder* DIBuilderRef;
|
||||
|
||||
template<typename DIT>
|
||||
DIT unwrapDI(LLVMValueRef ref) {
|
||||
return DIT(ref ? unwrap<MDNode>(ref) : NULL);
|
||||
DIT unwrapDI(LLVMValueRef ref) {
|
||||
return DIT(ref ? unwrap<MDNode>(ref) : NULL);
|
||||
}
|
||||
|
||||
extern "C" DIBuilderRef LLVMDIBuilderCreate(LLVMModuleRef M) {
|
||||
|
@ -604,21 +604,21 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateFile(
|
|||
|
||||
extern "C" LLVMValueRef LLVMDIBuilderCreateSubroutineType(
|
||||
DIBuilderRef Builder,
|
||||
LLVMValueRef File,
|
||||
LLVMValueRef File,
|
||||
LLVMValueRef ParameterTypes) {
|
||||
return wrap(Builder->createSubroutineType(
|
||||
unwrapDI<DIFile>(File),
|
||||
unwrapDI<DIFile>(File),
|
||||
unwrapDI<DIArray>(ParameterTypes)));
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef LLVMDIBuilderCreateFunction(
|
||||
DIBuilderRef Builder,
|
||||
LLVMValueRef Scope,
|
||||
LLVMValueRef Scope,
|
||||
const char* Name,
|
||||
const char* LinkageName,
|
||||
LLVMValueRef File,
|
||||
LLVMValueRef File,
|
||||
unsigned LineNo,
|
||||
LLVMValueRef Ty,
|
||||
LLVMValueRef Ty,
|
||||
bool isLocalToUnit,
|
||||
bool isDefinition,
|
||||
unsigned ScopeLine,
|
||||
|
@ -628,11 +628,11 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateFunction(
|
|||
LLVMValueRef TParam,
|
||||
LLVMValueRef Decl) {
|
||||
return wrap(Builder->createFunction(
|
||||
unwrapDI<DIScope>(Scope), Name, LinkageName,
|
||||
unwrapDI<DIFile>(File), LineNo,
|
||||
unwrapDI<DIType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
|
||||
unwrapDI<DIScope>(Scope), Name, LinkageName,
|
||||
unwrapDI<DIFile>(File), LineNo,
|
||||
unwrapDI<DIType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
|
||||
Flags, isOptimized,
|
||||
unwrap<Function>(Fn),
|
||||
unwrap<Function>(Fn),
|
||||
unwrapDI<MDNode*>(TParam),
|
||||
unwrapDI<MDNode*>(Decl)));
|
||||
}
|
||||
|
@ -644,10 +644,10 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateBasicType(
|
|||
uint64_t AlignInBits,
|
||||
unsigned Encoding) {
|
||||
return wrap(Builder->createBasicType(
|
||||
Name, SizeInBits,
|
||||
Name, SizeInBits,
|
||||
AlignInBits, Encoding));
|
||||
}
|
||||
|
||||
|
||||
extern "C" LLVMValueRef LLVMDIBuilderCreatePointerType(
|
||||
DIBuilderRef Builder,
|
||||
LLVMValueRef PointeeTy,
|
||||
|
@ -672,11 +672,11 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateStructType(
|
|||
unsigned RunTimeLang,
|
||||
LLVMValueRef VTableHolder) {
|
||||
return wrap(Builder->createStructType(
|
||||
unwrapDI<DIDescriptor>(Scope), Name,
|
||||
unwrapDI<DIFile>(File), LineNumber,
|
||||
SizeInBits, AlignInBits, Flags,
|
||||
unwrapDI<DIType>(DerivedFrom),
|
||||
unwrapDI<DIArray>(Elements), RunTimeLang,
|
||||
unwrapDI<DIDescriptor>(Scope), Name,
|
||||
unwrapDI<DIFile>(File), LineNumber,
|
||||
SizeInBits, AlignInBits, Flags,
|
||||
unwrapDI<DIType>(DerivedFrom),
|
||||
unwrapDI<DIArray>(Elements), RunTimeLang,
|
||||
unwrapDI<MDNode*>(VTableHolder)));
|
||||
}
|
||||
|
||||
|
@ -692,12 +692,12 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateMemberType(
|
|||
unsigned Flags,
|
||||
LLVMValueRef Ty) {
|
||||
return wrap(Builder->createMemberType(
|
||||
unwrapDI<DIDescriptor>(Scope), Name,
|
||||
unwrapDI<DIDescriptor>(Scope), Name,
|
||||
unwrapDI<DIFile>(File), LineNo,
|
||||
SizeInBits, AlignInBits, OffsetInBits, Flags,
|
||||
SizeInBits, AlignInBits, OffsetInBits, Flags,
|
||||
unwrapDI<DIType>(Ty)));
|
||||
}
|
||||
|
||||
|
||||
extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock(
|
||||
DIBuilderRef Builder,
|
||||
LLVMValueRef Scope,
|
||||
|
@ -705,10 +705,10 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock(
|
|||
unsigned Line,
|
||||
unsigned Col) {
|
||||
return wrap(Builder->createLexicalBlock(
|
||||
unwrapDI<DIDescriptor>(Scope),
|
||||
unwrapDI<DIDescriptor>(Scope),
|
||||
unwrapDI<DIFile>(File), Line, Col));
|
||||
}
|
||||
|
||||
|
||||
extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable(
|
||||
DIBuilderRef Builder,
|
||||
unsigned Tag,
|
||||
|
@ -720,45 +720,45 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable(
|
|||
bool AlwaysPreserve,
|
||||
unsigned Flags,
|
||||
unsigned ArgNo) {
|
||||
return wrap(Builder->createLocalVariable(Tag,
|
||||
unwrapDI<DIDescriptor>(Scope), Name,
|
||||
unwrapDI<DIFile>(File),
|
||||
LineNo,
|
||||
return wrap(Builder->createLocalVariable(Tag,
|
||||
unwrapDI<DIDescriptor>(Scope), Name,
|
||||
unwrapDI<DIFile>(File),
|
||||
LineNo,
|
||||
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo));
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef LLVMDIBuilderCreateArrayType(
|
||||
DIBuilderRef Builder,
|
||||
uint64_t Size,
|
||||
uint64_t AlignInBits,
|
||||
LLVMValueRef Ty,
|
||||
uint64_t Size,
|
||||
uint64_t AlignInBits,
|
||||
LLVMValueRef Ty,
|
||||
LLVMValueRef Subscripts) {
|
||||
return wrap(Builder->createArrayType(Size, AlignInBits,
|
||||
unwrapDI<DIType>(Ty),
|
||||
unwrapDI<DIType>(Ty),
|
||||
unwrapDI<DIArray>(Subscripts)));
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef LLVMDIBuilderCreateVectorType(
|
||||
DIBuilderRef Builder,
|
||||
uint64_t Size,
|
||||
uint64_t AlignInBits,
|
||||
LLVMValueRef Ty,
|
||||
uint64_t Size,
|
||||
uint64_t AlignInBits,
|
||||
LLVMValueRef Ty,
|
||||
LLVMValueRef Subscripts) {
|
||||
return wrap(Builder->createVectorType(Size, AlignInBits,
|
||||
unwrapDI<DIType>(Ty),
|
||||
unwrapDI<DIType>(Ty),
|
||||
unwrapDI<DIArray>(Subscripts)));
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateSubrange(
|
||||
DIBuilderRef Builder,
|
||||
int64_t Lo,
|
||||
DIBuilderRef Builder,
|
||||
int64_t Lo,
|
||||
int64_t Count) {
|
||||
return wrap(Builder->getOrCreateSubrange(Lo, Count));
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateArray(
|
||||
DIBuilderRef Builder,
|
||||
LLVMValueRef* Ptr,
|
||||
LLVMValueRef* Ptr,
|
||||
unsigned Count) {
|
||||
return wrap(Builder->getOrCreateArray(
|
||||
ArrayRef<Value*>(reinterpret_cast<Value**>(Ptr), Count)));
|
||||
|
@ -770,8 +770,8 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
|
|||
LLVMValueRef VarInfo,
|
||||
LLVMBasicBlockRef InsertAtEnd) {
|
||||
return wrap(Builder->insertDeclare(
|
||||
unwrap(Val),
|
||||
unwrapDI<DIVariable>(VarInfo),
|
||||
unwrap(Val),
|
||||
unwrapDI<DIVariable>(VarInfo),
|
||||
unwrap(InsertAtEnd)));
|
||||
}
|
||||
|
||||
|
@ -781,8 +781,8 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
|
|||
LLVMValueRef VarInfo,
|
||||
LLVMValueRef InsertBefore) {
|
||||
return wrap(Builder->insertDeclare(
|
||||
unwrap(Val),
|
||||
unwrapDI<DIVariable>(VarInfo),
|
||||
unwrap(Val),
|
||||
unwrapDI<DIVariable>(VarInfo),
|
||||
unwrap<Instruction>(InsertBefore)));
|
||||
}
|
||||
|
||||
|
@ -814,4 +814,28 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateEnumerationType(
|
|||
AlignInBits,
|
||||
unwrapDI<DIArray>(Elements),
|
||||
unwrapDI<DIType>(ClassType)));
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
|
||||
DIBuilderRef Builder,
|
||||
LLVMValueRef Scope,
|
||||
const char* Name,
|
||||
LLVMValueRef File,
|
||||
unsigned LineNumber,
|
||||
uint64_t SizeInBits,
|
||||
uint64_t AlignInBits,
|
||||
unsigned Flags,
|
||||
LLVMValueRef Elements,
|
||||
unsigned RunTimeLang)
|
||||
{
|
||||
return wrap(Builder->createUnionType(
|
||||
unwrapDI<DIDescriptor>(Scope),
|
||||
Name,
|
||||
unwrapDI<DIFile>(File),
|
||||
LineNumber,
|
||||
SizeInBits,
|
||||
AlignInBits,
|
||||
Flags,
|
||||
unwrapDI<DIArray>(Elements),
|
||||
RunTimeLang));
|
||||
}
|
|
@ -31,19 +31,25 @@
|
|||
// debugger:print manual_one_million
|
||||
// check:$6 = OneMillion
|
||||
|
||||
// debugger:print single_variant
|
||||
// check:$7 = TheOnlyVariant
|
||||
|
||||
enum AutoDiscriminator {
|
||||
enum AutoDiscriminant {
|
||||
One,
|
||||
Two,
|
||||
Three
|
||||
}
|
||||
|
||||
enum ManualDiscriminator {
|
||||
enum ManualDiscriminant {
|
||||
OneHundred = 100,
|
||||
OneThousand = 1000,
|
||||
OneMillion = 1000000
|
||||
}
|
||||
|
||||
enum SingleVariant {
|
||||
TheOnlyVariant
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
let auto_one = One;
|
||||
|
@ -54,6 +60,8 @@ fn main() {
|
|||
let manual_one_thousand = OneThousand;
|
||||
let manual_one_million = OneMillion;
|
||||
|
||||
let single_variant = TheOnlyVariant;
|
||||
|
||||
zzz();
|
||||
}
|
||||
|
||||
|
|
38
src/test/debug-info/nil-enum.rs
Normal file
38
src/test/debug-info/nil-enum.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
// compile-flags:-Z extra-debug-info
|
||||
// debugger:break zzz
|
||||
// debugger:run
|
||||
// debugger:finish
|
||||
|
||||
// debugger:print first
|
||||
// check:$1 = {<No data fields>}
|
||||
|
||||
// debugger:print second
|
||||
// check:$2 = {<No data fields>}
|
||||
|
||||
enum ANilEnum {}
|
||||
enum AnotherNilEnum {}
|
||||
|
||||
// I (mw) am not sure this test case makes much sense...
|
||||
// Also, it relies on some implementation details:
|
||||
// 1. That empty enums as well as '()' are represented as empty structs
|
||||
// 2. That gdb prints the string "{<No data fields>}" for empty structs (which may change some time)
|
||||
fn main() {
|
||||
unsafe {
|
||||
let first : ANilEnum = std::cast::transmute(());
|
||||
let second : AnotherNilEnum = std::cast::transmute(());
|
||||
|
||||
zzz();
|
||||
}
|
||||
}
|
||||
|
||||
fn zzz() {()}
|
33
src/test/debug-info/tuple-style-enum.rs
Normal file
33
src/test/debug-info/tuple-style-enum.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
// compile-flags:-Z extra-debug-info
|
||||
// debugger:set print union on
|
||||
// debugger:break zzz
|
||||
// debugger:run
|
||||
// debugger:finish
|
||||
|
||||
// debugger:print case2
|
||||
// check:$1 = {Case1, 0, 1}
|
||||
|
||||
enum Test {
|
||||
Case1(i32, i64),
|
||||
Case2(bool, i16, i32)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
let case1 = Case1(110, 220);
|
||||
let case2 = Case2(false, 2, 3);
|
||||
|
||||
zzz();
|
||||
}
|
||||
|
||||
fn zzz() {()}
|
Loading…
Add table
Reference in a new issue