diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 1e70664e64d7..0e42931b29a9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -471,21 +471,28 @@ fn trait_pointer_metadata( // type is assigned the correct name, size, namespace, and source location. // However, it does not describe the trait's methods. - let containing_scope = match trait_type.kind() { - ty::Dynamic(ref data, ..) => { - data.principal_def_id().map(|did| get_namespace_for_item(cx, did)) - } - _ => { - bug!( - "debuginfo: unexpected trait-object type in \ - trait_pointer_metadata(): {:?}", - trait_type - ); - } - }; + let (containing_scope, trait_type_name) = match trait_object_type { + Some(trait_object_type) => match trait_object_type.kind() { + ty::Adt(def, _) => ( + Some(get_namespace_for_item(cx, def.did)), + compute_debuginfo_type_name(cx.tcx, trait_object_type, false), + ), + ty::RawPtr(_) | ty::Ref(..) => { + (NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_object_type, true)) + } + _ => { + bug!( + "debuginfo: unexpected trait-object type in \ + trait_pointer_metadata(): {:?}", + trait_object_type + ); + } + }, - let trait_object_type = trait_object_type.unwrap_or(trait_type); - let trait_type_name = compute_debuginfo_type_name(cx.tcx, trait_object_type, false); + // No object type, use the trait type directly (no scope here since the type + // will be wrapped in the dyn$ synthetic type). + None => (NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_type, true)), + }; let file_metadata = unknown_file_metadata(cx); @@ -525,7 +532,7 @@ fn trait_pointer_metadata( composite_type_metadata( cx, - trait_object_type, + trait_object_type.unwrap_or(trait_type), &trait_type_name[..], unique_type_id, member_descriptions, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 2b99a2ebad97..8375d4c7ca56 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -5,7 +5,6 @@ use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; use self::metadata::{file_metadata, type_metadata, TypeMap}; use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER}; use self::namespace::mangled_name_of_instance; -use self::type_names::compute_debuginfo_type_name; use self::utils::{create_DIArray, is_node_local_to_unit, DIB}; use crate::abi::FnAbi; @@ -311,10 +310,10 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), fn_signature) }; - // Find the enclosing function, in case this is a closure. - let def_key = self.tcx().def_key(def_id); - let mut name = def_key.disambiguated_data.data.to_string(); + let mut name = String::new(); + type_names::push_item_name(self.tcx(), def_id, false, &mut name); + // Find the enclosing function, in case this is a closure. let enclosing_fn_def_id = self.tcx().closure_base_def_id(def_id); // Get_template_parameters() will append a `<...>` clause to the function @@ -428,24 +427,16 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { substs: SubstsRef<'tcx>, name_to_append_suffix_to: &mut String, ) -> &'ll DIArray { + type_names::push_generic_params( + cx.tcx, + cx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs), + name_to_append_suffix_to, + ); + if substs.types().next().is_none() { return create_DIArray(DIB(cx), &[]); } - name_to_append_suffix_to.push('<'); - for (i, actual_type) in substs.types().enumerate() { - if i != 0 { - name_to_append_suffix_to.push(','); - } - - let actual_type = - cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), actual_type); - // Add actual type name to <...> clause of function name - let actual_type_name = compute_debuginfo_type_name(cx.tcx(), actual_type, true); - name_to_append_suffix_to.push_str(&actual_type_name[..]); - } - name_to_append_suffix_to.push('>'); - // Again, only create type information if full debuginfo is enabled let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full { let names = get_parameter_names(cx, generics); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs index 9945d4f42825..1cbf53869960 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs @@ -1,13 +1,13 @@ // Namespace Handling. use super::utils::{debug_context, DIB}; +use rustc_codegen_ssa::debuginfo::type_names; use rustc_middle::ty::{self, Instance}; use crate::common::CodegenCx; use crate::llvm; use crate::llvm::debuginfo::DIScope; use rustc_hir::def_id::DefId; -use rustc_hir::definitions::DefPathData; pub fn mangled_name_of_instance<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, @@ -27,25 +27,18 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { .parent .map(|parent| item_namespace(cx, DefId { krate: def_id.krate, index: parent })); - let crate_name_as_str; - let name_to_string; - let namespace_name = match def_key.disambiguated_data.data { - DefPathData::CrateRoot => { - crate_name_as_str = cx.tcx.crate_name(def_id.krate).as_str(); - &*crate_name_as_str - } - data => { - name_to_string = data.to_string(); - &*name_to_string - } + let namespace_name_string = { + let mut output = String::new(); + type_names::push_item_name(cx.tcx, def_id, false, &mut output); + output }; let scope = unsafe { llvm::LLVMRustDIBuilderCreateNameSpace( DIB(cx), parent_scope, - namespace_name.as_ptr().cast(), - namespace_name.len(), + namespace_name_string.as_ptr().cast(), + namespace_name_string.len(), false, // ExportSymbols (only relevant for C++ anonymous namespaces) ) }; diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 7b4b0821c4be..a97c6a6b4429 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -1,9 +1,22 @@ // Type Names for Debug Info. +// Notes on targetting MSVC: +// In general, MSVC's debugger attempts to parse all arguments as C++ expressions, +// even if the argument is explicitly a symbol name. +// As such, there are many things that cause parsing issues: +// * `#` is treated as a special character for macros. +// * `{` or `<` at the beginning of a name is treated as an operator. +// * `>>` is always treated as a right-shift. +// * `[` in a name is treated like a regex bracket expression (match any char +// within the brackets). +// * `"` is treated as the start of a string. + use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty, TyCtxt}; +use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; +use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; +use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_target::abi::{TagEncoding, Variants}; use std::fmt::Write; @@ -40,7 +53,13 @@ pub fn push_debuginfo_type_name<'tcx>( ty::Bool => output.push_str("bool"), ty::Char => output.push_str("char"), ty::Str => output.push_str("str"), - ty::Never => output.push('!'), + ty::Never => { + if cpp_like_names { + output.push_str("never$"); + } else { + output.push('!'); + } + } ty::Int(int_ty) => output.push_str(int_ty.name_str()), ty::Uint(uint_ty) => output.push_str(uint_ty.name_str()), ty::Float(float_ty) => output.push_str(float_ty.name_str()), @@ -50,74 +69,109 @@ pub fn push_debuginfo_type_name<'tcx>( msvc_enum_fallback(tcx, t, def, substs, output, visited); } else { push_item_name(tcx, def.did, qualified, output); - push_type_params(tcx, substs, output, visited); + push_generic_params_internal(tcx, substs, output, visited); } } ty::Tuple(component_types) => { if cpp_like_names { - output.push_str("tuple<"); + output.push_str("tuple$<"); } else { output.push('('); } for component_type in component_types { push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited); - output.push_str(", "); + output.push(','); + + // Natvis does not always like having spaces between parts of the type name + // and this causes issues when we need to write a typename in natvis, for example + // as part of a cast like the `HashMap` visualizer does. + if !cpp_like_names { + output.push(' '); + } } if !component_types.is_empty() { output.pop(); - output.pop(); + + if !cpp_like_names { + output.pop(); + } } if cpp_like_names { - output.push('>'); + push_close_angle_bracket(tcx, output); } else { output.push(')'); } } ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => { - if !cpp_like_names { + if cpp_like_names { + match mutbl { + hir::Mutability::Not => output.push_str("ptr_const$<"), + hir::Mutability::Mut => output.push_str("ptr_mut$<"), + } + } else { output.push('*'); - } - match mutbl { - hir::Mutability::Not => output.push_str("const "), - hir::Mutability::Mut => output.push_str("mut "), + match mutbl { + hir::Mutability::Not => output.push_str("const "), + hir::Mutability::Mut => output.push_str("mut "), + } } - push_debuginfo_type_name(tcx, inner_type, true, output, visited); + push_debuginfo_type_name(tcx, inner_type, qualified, output, visited); if cpp_like_names { - output.push('*'); + push_close_angle_bracket(tcx, output); } } ty::Ref(_, inner_type, mutbl) => { + // Slices and `&str` are treated like C++ pointers when computing debug + // info for MSVC debugger. However, wrapping these types' names in a synthetic type + // causes the .natvis engine for WinDbg to fail to display their data, so we opt these + // types out to aid debugging in MSVC. + let is_slice_or_str = match *inner_type.kind() { + ty::Slice(_) | ty::Str => true, + _ => false, + }; + if !cpp_like_names { output.push('&'); + output.push_str(mutbl.prefix_str()); + } else if !is_slice_or_str { + match mutbl { + hir::Mutability::Not => output.push_str("ref$<"), + hir::Mutability::Mut => output.push_str("ref_mut$<"), + } } - output.push_str(mutbl.prefix_str()); - push_debuginfo_type_name(tcx, inner_type, true, output, visited); + push_debuginfo_type_name(tcx, inner_type, qualified, output, visited); - if cpp_like_names { - // Slices and `&str` are treated like C++ pointers when computing debug - // info for MSVC debugger. However, adding '*' at the end of these types' names - // causes the .natvis engine for WinDbg to fail to display their data, so we opt these - // types out to aid debugging in MSVC. - match *inner_type.kind() { - ty::Slice(_) | ty::Str => {} - _ => output.push('*'), - } + if cpp_like_names && !is_slice_or_str { + push_close_angle_bracket(tcx, output); } } ty::Array(inner_type, len) => { - output.push('['); - push_debuginfo_type_name(tcx, inner_type, true, output, visited); - output.push_str(&format!("; {}", len.eval_usize(tcx, ty::ParamEnv::reveal_all()))); - output.push(']'); + if cpp_like_names { + output.push_str("array$<"); + push_debuginfo_type_name(tcx, inner_type, true, output, visited); + match len.val { + ty::ConstKind::Param(param) => write!(output, ",{}>", param.name).unwrap(), + _ => write!(output, ",{}>", len.eval_usize(tcx, ty::ParamEnv::reveal_all())) + .unwrap(), + } + } else { + output.push('['); + push_debuginfo_type_name(tcx, inner_type, true, output, visited); + match len.val { + ty::ConstKind::Param(param) => write!(output, "; {}]", param.name).unwrap(), + _ => write!(output, "; {}]", len.eval_usize(tcx, ty::ParamEnv::reveal_all())) + .unwrap(), + } + } } ty::Slice(inner_type) => { if cpp_like_names { - output.push_str("slice<"); + output.push_str("slice$<"); } else { output.push('['); } @@ -125,19 +179,69 @@ pub fn push_debuginfo_type_name<'tcx>( push_debuginfo_type_name(tcx, inner_type, true, output, visited); if cpp_like_names { - output.push('>'); + push_close_angle_bracket(tcx, output); } else { output.push(']'); } } ty::Dynamic(ref trait_data, ..) => { + if cpp_like_names { + output.push_str("dyn$<"); + } else { + output.push_str("dyn "); + } + if let Some(principal) = trait_data.principal() { let principal = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal); - push_item_name(tcx, principal.def_id, false, output); - push_type_params(tcx, principal.substs, output, visited); + push_item_name(tcx, principal.def_id, qualified, output); + push_generic_params_internal(tcx, principal.substs, output, visited); } else { - output.push_str("dyn '_"); + // The auto traits come ordered by `DefPathHash`, which guarantees stability if the + // environment is stable (e.g., incremental builds) but not otherwise (e.g., + // updated compiler version, different target). + // + // To avoid that causing instabilities in test output, sort the auto-traits + // alphabetically. + let mut auto_traits: Vec<_> = trait_data + .iter() + .filter_map(|predicate| { + match tcx.normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + predicate, + ) { + ty::ExistentialPredicate::AutoTrait(def_id) => { + let mut name = String::new(); + push_item_name(tcx, def_id, true, &mut name); + Some(name) + } + _ => None, + } + }) + .collect(); + auto_traits.sort(); + + for name in auto_traits { + output.push_str(&name); + + if cpp_like_names { + output.push_str(", "); + } else { + output.push_str(" + "); + } + } + + // Remove the trailing joining characters. For cpp_like_names + // this is `, ` otherwise ` + `. + output.pop(); + output.pop(); + if !cpp_like_names { + output.pop(); + } + } + + if cpp_like_names { + push_close_angle_bracket(tcx, output); } } ty::FnDef(..) | ty::FnPtr(_) => { @@ -155,23 +259,37 @@ pub fn push_debuginfo_type_name<'tcx>( // use a dummy string that should make it clear // that something unusual is going on if !visited.insert(t) { - output.push_str(""); + output.push_str(if cpp_like_names { + "recursive_type$" + } else { + "" + }); return; } - let sig = t.fn_sig(tcx); - output.push_str(sig.unsafety().prefix_str()); + let sig = + tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), t.fn_sig(tcx)); - let abi = sig.abi(); - if abi != rustc_target::spec::abi::Abi::Rust { - output.push_str("extern \""); - output.push_str(abi.name()); - output.push_str("\" "); - } + if cpp_like_names { + // Format as a C++ function pointer: return_type (*)(params...) + if sig.output().is_unit() { + output.push_str("void"); + } else { + push_debuginfo_type_name(tcx, sig.output(), true, output, visited); + } + output.push_str(" (*)("); + } else { + output.push_str(sig.unsafety.prefix_str()); + + if sig.abi != rustc_target::spec::abi::Abi::Rust { + output.push_str("extern \""); + output.push_str(sig.abi.name()); + output.push_str("\" "); + } - output.push_str("fn("); + output.push_str("fn("); + } - let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); if !sig.inputs().is_empty() { for ¶meter_type in sig.inputs() { push_debuginfo_type_name(tcx, parameter_type, true, output, visited); @@ -191,7 +309,7 @@ pub fn push_debuginfo_type_name<'tcx>( output.push(')'); - if !sig.output().is_unit() { + if !cpp_like_names && !sig.output().is_unit() { output.push_str(" -> "); push_debuginfo_type_name(tcx, sig.output(), true, output, visited); } @@ -207,17 +325,14 @@ pub fn push_debuginfo_type_name<'tcx>( // processing visited.remove(t); } - ty::Closure(def_id, ..) => { - output.push_str(&format!( - "closure-{}", - tcx.def_key(def_id).disambiguated_data.disambiguator - )); - } - ty::Generator(def_id, ..) => { - output.push_str(&format!( - "generator-{}", - tcx.def_key(def_id).disambiguated_data.disambiguator - )); + ty::Closure(def_id, ..) | ty::Generator(def_id, ..) => { + let key = tcx.def_key(def_id); + if qualified { + let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; + push_item_name(tcx, parent_def_id, true, output); + output.push_str("::"); + } + push_unqualified_item_name(tcx, def_id, key.disambiguated_data, output); } // Type parameters from polymorphized functions. ty::Param(_) => { @@ -273,7 +388,7 @@ pub fn push_debuginfo_type_name<'tcx>( output.push_str("enum$<"); push_item_name(tcx, def.did, true, output); - push_type_params(tcx, substs, output, visited); + push_generic_params_internal(tcx, substs, output, visited); let dataful_variant_name = def.variants[*dataful_variant].ident.as_str(); @@ -281,47 +396,116 @@ pub fn push_debuginfo_type_name<'tcx>( } else { output.push_str("enum$<"); push_item_name(tcx, def.did, true, output); - push_type_params(tcx, substs, output, visited); - output.push('>'); + push_generic_params_internal(tcx, substs, output, visited); + push_close_angle_bracket(tcx, output); } } +} + +pub fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) { + let def_key = tcx.def_key(def_id); + if qualified { + if let Some(parent) = def_key.parent { + push_item_name(tcx, DefId { krate: def_id.krate, index: parent }, true, output); + output.push_str("::"); + } + } + + push_unqualified_item_name(tcx, def_id, def_key.disambiguated_data, output); +} - fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) { - if qualified { +fn push_unqualified_item_name( + tcx: TyCtxt<'tcx>, + def_id: DefId, + disambiguated_data: DisambiguatedDefPathData, + output: &mut String, +) { + let cpp_like_names = tcx.sess.target.is_like_msvc; + + match disambiguated_data.data { + DefPathData::CrateRoot => { output.push_str(&tcx.crate_name(def_id.krate).as_str()); - for path_element in tcx.def_path(def_id).data { - write!(output, "::{}", path_element.data).unwrap(); + } + DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => { + // Generators look like closures, but we want to treat them differently + // in the debug info. + if cpp_like_names { + write!(output, "generator${}", disambiguated_data.disambiguator).unwrap(); + } else { + write!(output, "{{generator#{}}}", disambiguated_data.disambiguator).unwrap(); } - } else { - output.push_str(&tcx.item_name(def_id).as_str()); } + _ => match disambiguated_data.data.name() { + DefPathDataName::Named(name) => { + output.push_str(&name.as_str()); + } + DefPathDataName::Anon { namespace } => { + if cpp_like_names { + write!(output, "{}${}", namespace, disambiguated_data.disambiguator).unwrap(); + } else { + write!(output, "{{{}#{}}}", namespace, disambiguated_data.disambiguator) + .unwrap(); + } + } + }, + }; +} + +// Pushes the generic parameters in the given `InternalSubsts` to the output string. +// This ignores region parameters, since they can't reliably be +// reconstructed for items from non-local crates. For local crates, this +// would be possible but with inlining and LTO we have to use the least +// common denominator - otherwise we would run into conflicts. +fn push_generic_params_internal<'tcx>( + tcx: TyCtxt<'tcx>, + substs: SubstsRef<'tcx>, + output: &mut String, + visited: &mut FxHashSet>, +) { + if substs.non_erasable_generics().next().is_none() { + return; } - // Pushes the type parameters in the given `InternalSubsts` to the output string. - // This ignores region parameters, since they can't reliably be - // reconstructed for items from non-local crates. For local crates, this - // would be possible but with inlining and LTO we have to use the least - // common denominator - otherwise we would run into conflicts. - fn push_type_params<'tcx>( - tcx: TyCtxt<'tcx>, - substs: SubstsRef<'tcx>, - output: &mut String, - visited: &mut FxHashSet>, - ) { - if substs.types().next().is_none() { - return; - } + debug_assert_eq!(substs, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs)); - output.push('<'); + output.push('<'); - for type_parameter in substs.types() { - push_debuginfo_type_name(tcx, type_parameter, true, output, visited); - output.push_str(", "); + for type_parameter in substs.non_erasable_generics() { + match type_parameter { + GenericArgKind::Type(type_parameter) => { + push_debuginfo_type_name(tcx, type_parameter, true, output, visited); + output.push_str(", "); + } + GenericArgKind::Const(const_parameter) => match const_parameter.val { + ty::ConstKind::Param(param) => write!(output, "{}, ", param.name).unwrap(), + _ => write!( + output, + "0x{:x}, ", + const_parameter.eval_bits(tcx, ty::ParamEnv::reveal_all(), const_parameter.ty) + ) + .unwrap(), + }, + other => bug!("Unexpected non-erasable generic: {:?}", other), } + } - output.pop(); - output.pop(); + output.pop(); + output.pop(); - output.push('>'); - } + push_close_angle_bracket(tcx, output); +} + +pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, output: &mut String) { + let mut visited = FxHashSet::default(); + push_generic_params_internal(tcx, substs, output, &mut visited); +} + +fn push_close_angle_bracket<'tcx>(tcx: TyCtxt<'tcx>, output: &mut String) { + // MSVC debugger always treats `>>` as a shift, even when parsing templates, + // so add a space to avoid confusion. + if tcx.sess.target.is_like_msvc && output.ends_with('>') { + output.push(' ') + }; + + output.push('>'); } diff --git a/src/etc/natvis/intrinsic.natvis b/src/etc/natvis/intrinsic.natvis index 89280149a035..cf887ffb0c01 100644 --- a/src/etc/natvis/intrinsic.natvis +++ b/src/etc/natvis/intrinsic.natvis @@ -15,7 +15,7 @@ - + {{ len={length} }} length @@ -25,23 +25,23 @@ - + () - + ({__0}) __0 - + ({__0}, {__1}) __0 __1 - + ({__0}, {__1}, {__2}) __0 @@ -49,7 +49,7 @@ __2 - + ({__0}, {__1}, {__2}, {__3}) __0 @@ -58,7 +58,7 @@ __3 - + ({__0}, {__1}, {__2}, {__3}, {__4}) __0 @@ -68,7 +68,7 @@ __4 - + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}) __0 @@ -79,7 +79,7 @@ __5 - + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}) __0 @@ -91,7 +91,7 @@ __6 - + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}) __0 @@ -104,7 +104,7 @@ __7 - + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}) __0 @@ -118,7 +118,7 @@ __8 - + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}, {__9}) __0 @@ -133,7 +133,7 @@ __9 - + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}, {__9}, ...) __0 diff --git a/src/etc/natvis/libstd.natvis b/src/etc/natvis/libstd.natvis index 2c05f9d7c12e..3ccd2e9c30ed 100644 --- a/src/etc/natvis/libstd.natvis +++ b/src/etc/natvis/libstd.natvis @@ -41,7 +41,7 @@ n-- - ((tuple<$T1, $T2>*)base.table.table.ctrl.pointer)[-(i + 1)].__1 + ((tuple$<$T1, $T2>*)base.table.table.ctrl.pointer)[-(i + 1)].__1 i++ diff --git a/src/test/codegen/async-fn-debug-msvc.rs b/src/test/codegen/async-fn-debug-msvc.rs index e410180bfff6..8efa1b15b3ff 100644 --- a/src/test/codegen/async-fn-debug-msvc.rs +++ b/src/test/codegen/async-fn-debug-msvc.rs @@ -17,7 +17,7 @@ async fn async_fn_test() { // FIXME: No way to reliably check the filename. // CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0" +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator$0" // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]], // For brevity, we only check the struct name and members of the last variant. // CHECK-SAME: file: [[FILE:![0-9]*]], line: 11, diff --git a/src/test/codegen/async-fn-debug.rs b/src/test/codegen/async-fn-debug.rs index 7de115f7e919..39319a3ea722 100644 --- a/src/test/codegen/async-fn-debug.rs +++ b/src/test/codegen/async-fn-debug.rs @@ -17,7 +17,7 @@ async fn async_fn_test() { // FIXME: No way to reliably check the filename. // CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[ASYNC_FN]] +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator#0}", scope: [[ASYNC_FN]] // CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[ASYNC_FN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] diff --git a/src/test/codegen/fn-impl-trait-self.rs b/src/test/codegen/fn-impl-trait-self.rs index f9113d50197c..4bd811bed10e 100644 --- a/src/test/codegen/fn-impl-trait-self.rs +++ b/src/test/codegen/fn-impl-trait-self.rs @@ -1,7 +1,8 @@ // compile-flags: -g // // CHECK-LABEL: @main -// CHECK: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> ",{{.*}} +// MSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "recursive_type$ (*)()",{{.*}} +// NONMSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> ",{{.*}} // // CHECK: {{.*}}DISubroutineType{{.*}} // CHECK: {{.*}}DIBasicType(name: "", encoding: DW_ATE_unsigned) diff --git a/src/test/codegen/generator-debug-msvc.rs b/src/test/codegen/generator-debug-msvc.rs index 7edb07d224c3..e2ba4ad30894 100644 --- a/src/test/codegen/generator-debug-msvc.rs +++ b/src/test/codegen/generator-debug-msvc.rs @@ -21,7 +21,7 @@ fn generator_test() -> impl Generator { // FIXME: No way to reliably check the filename. // CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0" +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator$0" // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]], // For brevity, we only check the struct name and members of the last variant. // CHECK-SAME: file: [[FILE:![0-9]*]], line: 14, diff --git a/src/test/codegen/generator-debug.rs b/src/test/codegen/generator-debug.rs index 8b87a2f06460..ea324695c15d 100644 --- a/src/test/codegen/generator-debug.rs +++ b/src/test/codegen/generator-debug.rs @@ -21,7 +21,7 @@ fn generator_test() -> impl Generator { // FIXME: No way to reliably check the filename. // CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[GEN_FN]] +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator#0}", scope: [[GEN_FN]] // CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[GEN_FN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs index 3721b87678d5..c35c32554983 100644 --- a/src/test/debuginfo/basic-types.rs +++ b/src/test/debuginfo/basic-types.rs @@ -6,9 +6,8 @@ // min-lldb-version: 310 -// This fails on lldb 6.0.1 on x86-64 Fedora 28; so mark it macOS-only -// for now. -// only-macos +// This fails on lldb 6.0.1 on x86-64 Fedora 28; so ignore Linux for now. +// ignore-linux // compile-flags:-g @@ -44,6 +43,9 @@ // gdb-check:$13 = 2.5 // gdb-command:print f64 // gdb-check:$14 = 3.5 +// gdb-command:print s +// gdbg-check:$15 = {data_ptr = [...] "Hello, World!", length = 13} +// gdbr-check:$15 = "Hello, World!" // === LLDB TESTS ================================================================================== @@ -94,6 +96,41 @@ // lldbg-check:[...]$12 = 3.5 // lldbr-check:(f64) f64 = 3.5 + +// === CDB TESTS =================================================================================== + +// cdb-command:g +// cdb-command:dx b +// cdb-check:b : false [Type: bool] +// cdb-command:dx i +// cdb-check:i : -1 [Type: [...]] +// The variable 'c' doesn't appear for some reason... +// cdb-command:dx i8 +// cdb-check:i8 : 68 [Type: char] +// cdb-command:dx i16 +// cdb-check:i16 : -16 [Type: short] +// cdb-command:dx i32 +// cdb-check:i32 : -32 [Type: int] +// cdb-command:dx i64 +// cdb-check:i64 : -64 [Type: __int64] +// cdb-command:dx u +// cdb-check:u : 0x1 [Type: [...]] +// cdb-command:dx u8 +// cdb-check:u8 : 0x64 [Type: unsigned char] +// cdb-command:dx u16 +// cdb-check:u16 : 0x10 [Type: unsigned short] +// cdb-command:dx u32 +// cdb-check:u32 : 0x20 [Type: unsigned int] +// cdb-command:dx u64 +// cdb-check:u64 : 0x40 [Type: unsigned __int64] +// cdb-command:dx f32 +// cdb-check:f32 : 2.500000 [Type: float] +// cdb-command:dx f64 +// cdb-check:f64 : 3.500000 [Type: double] +// cdb-command:.enable_unicode 1 +// cdb-command:dx s +// cdb-check:s : "Hello, World!" [Type: str] + #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -113,6 +150,7 @@ fn main() { let u64: u64 = 64; let f32: f32 = 2.5; let f64: f64 = 3.5; + let s: &str = "Hello, World!"; _zzz(); // #break } diff --git a/src/test/debuginfo/function-names.rs b/src/test/debuginfo/function-names.rs new file mode 100644 index 000000000000..26317f5c3ff3 --- /dev/null +++ b/src/test/debuginfo/function-names.rs @@ -0,0 +1,175 @@ +// Function names are formatted differently in old versions of GDB +// min-gdb-version: 9.2 + +// compile-flags:-g + +// === GDB TESTS =================================================================================== + +// Top-level function +// gdb-command:info functions -q function_names::main +// gdb-check:[...]static fn function_names::main(); +// gdb-command:info functions -q function_names::generic_func<* +// gdb-check:[...]static fn function_names::generic_func(i32) -> i32; + +// Implementations +// gdb-command:info functions -q function_names::.*::impl_function.* +// gdb-check:[...]static fn function_names::GenericStruct::impl_function(); +// gdb-check:[...]static fn function_names::Mod1::TestStruct2::impl_function(); +// gdb-check:[...]static fn function_names::TestStruct1::impl_function(); + +// Trait implementations +// gdb-command:info functions -q function_names::.*::trait_function.* +// gdb-check:[...]static fn as function_names::TestTrait1>::trait_function(); +// gdb-check:[...]static fn as function_names::TestTrait1>::trait_function(); +// gdb-check:[...]static fn ::trait_function(); +// gdb-check:[...]static fn ::trait_function(); + +// Closure +// gdb-command:info functions -q function_names::.*::{{closure.* +// gdb-check:[...]static fn function_names::GenericStruct::impl_function::{{closure}}(*mut function_names::{impl#2}::impl_function::{closure#0}); +// gdb-check:[...]static fn function_names::generic_func::{{closure}}(*mut function_names::generic_func::{closure#0}); +// gdb-check:[...]static fn function_names::main::{{closure}}(*mut function_names::main::{closure#0}); + +// Generator +// Generators don't seem to appear in GDB's symbol table. + +// === CDB TESTS =================================================================================== + +// Top-level function +// cdb-command:x a!function_names::main +// cdb-check:[...] a!function_names::main (void) +// cdb-command:x a!function_names::generic_func<* +// cdb-check:[...] a!function_names::generic_func (int) + +// Implementations +// cdb-command:x a!function_names::*::impl_function* +// cdb-check:[...] a!function_names::Mod1::TestStruct2::impl_function (void) +// cdb-check:[...] a!function_names::TestStruct1::impl_function (void) +// cdb-check:[...] a!function_names::GenericStruct::impl_function (void) + +// Trait implementations +// cdb-command:x a!function_names::*::trait_function* +// cdb-check:[...] a!function_names::impl$6::trait_function (void) +// cdb-check:[...] a!function_names::impl$3::trait_function (void) +// cdb-check:[...] a!function_names::impl$1::trait_function (void) +// cdb-check:[...] a!function_names::impl$5::trait_function3 (void) +// cdb-check:[...] a!function_names::Mod1::impl$1::trait_function (void) + +// Closure +// cdb-command:x a!function_names::*::closure* +// cdb-check:[...] a!function_names::main::closure$0 (void) +// cdb-check:[...] a!function_names::generic_func::closure$0 (void) +// cdb-check:[...] a!function_names::impl$2::impl_function::closure$0 (void) + +// Generator +// cdb-command:x a!function_names::*::generator* +// cdb-check:[...] a!function_names::main::generator$1 (void) + +#![allow(unused_variables)] +#![feature(omit_gdb_pretty_printer_section)] +#![omit_gdb_pretty_printer_section] +#![feature(generators, generator_trait)] + +use Mod1::TestTrait2; +use std::ops::Generator; +use std::pin::Pin; + +fn main() { + // Implementations + TestStruct1::impl_function(); + Mod1::TestStruct2::impl_function(); + GenericStruct::::impl_function(); + + // Trait implementations + TestStruct1::trait_function(); + Mod1::TestStruct2::trait_function(); + GenericStruct::::trait_function(); + GenericStruct::<[i32; 1], f32>::trait_function(); + GenericStruct::::trait_function3(); + + // Generic function + let _ = generic_func(42); + + // Closure + let closure = || { TestStruct1 }; + closure(); + + // Generator + let mut generator = || { yield; return; }; + Pin::new(&mut generator).resume(()); +} + +struct TestStruct1; +trait TestTrait1 { + fn trait_function(); +} + +// Implementation +impl TestStruct1 { + pub fn impl_function() {} +} + +// Implementation for a trait +impl TestTrait1 for TestStruct1 { + fn trait_function() {} +} + +// Implementation and implementation within a mod +mod Mod1 { + pub struct TestStruct2; + pub trait TestTrait2 { + fn trait_function(); + } + + impl TestStruct2 { + pub fn impl_function() {} + } + + impl TestTrait2 for TestStruct2 { + fn trait_function() {} + } +} + +struct GenericStruct(std::marker::PhantomData<(T1, T2)>); + +// Generic implementation +impl GenericStruct { + pub fn impl_function() { + // Closure in a generic implementation + let closure = || { TestStruct1 }; + closure(); + } +} + +// Generic trait implementation +impl TestTrait1 for GenericStruct { + fn trait_function() {} +} + +// Implementation based on associated type +trait TestTrait3 { + type AssocType; + fn trait_function3(); +} +impl TestTrait3 for TestStruct1 { + type AssocType = usize; + fn trait_function3() {} +} +impl TestTrait3 for GenericStruct { + type AssocType = T::AssocType; + fn trait_function3() {} +} + +// Generic trait implementation with const generics +impl TestTrait1 for GenericStruct<[T; N], f32> { + fn trait_function() {} +} + +// Generic function +fn generic_func(value: T) -> T { + // Closure in a generic function + let closure = || { TestStruct1 }; + closure(); + + value +} diff --git a/src/test/debuginfo/generator-objects.rs b/src/test/debuginfo/generator-objects.rs index 1beed1c835d9..7ac3304aa963 100644 --- a/src/test/debuginfo/generator-objects.rs +++ b/src/test/debuginfo/generator-objects.rs @@ -11,31 +11,31 @@ // gdb-command:run // gdb-command:print b -// gdb-check:$1 = generator_objects::main::generator-0::Unresumed(0x[...]) +// gdb-check:$1 = generator_objects::main::{generator#0}::Unresumed(0x[...]) // gdb-command:continue // gdb-command:print b -// gdb-check:$2 = generator_objects::main::generator-0::Suspend0{c: 6, d: 7, __0: 0x[...]} +// gdb-check:$2 = generator_objects::main::{generator#0}::Suspend0{c: 6, d: 7, __0: 0x[...]} // gdb-command:continue // gdb-command:print b -// gdb-check:$3 = generator_objects::main::generator-0::Suspend1{c: 7, d: 8, __0: 0x[...]} +// gdb-check:$3 = generator_objects::main::{generator#0}::Suspend1{c: 7, d: 8, __0: 0x[...]} // gdb-command:continue // gdb-command:print b -// gdb-check:$4 = generator_objects::main::generator-0::Returned(0x[...]) +// gdb-check:$4 = generator_objects::main::{generator#0}::Returned(0x[...]) // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $0 = +// lldbg-check:(generator_objects::main::{generator#0}) $0 = // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $1 = +// lldbg-check:(generator_objects::main::{generator#0}) $1 = // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $2 = +// lldbg-check:(generator_objects::main::{generator#0}) $2 = // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $3 = +// lldbg-check:(generator_objects::main::{generator#0}) $3 = #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)] #![omit_gdb_pretty_printer_section] diff --git a/src/test/debuginfo/generic-struct.rs b/src/test/debuginfo/generic-struct.rs index 170a610c621c..c0135de1219d 100644 --- a/src/test/debuginfo/generic-struct.rs +++ b/src/test/debuginfo/generic-struct.rs @@ -39,6 +39,27 @@ // lldbg-check:[...]$3 = AGenericStruct> { key: 6.5, value: AGenericStruct { key: 7, value: 8.5 } } // lldbr-check:(generic_struct::AGenericStruct>) float_int_float = AGenericStruct> { key: 6.5, value: AGenericStruct { key: 7, value: 8.5 } } +// === CDB TESTS =================================================================================== + +// cdb-command:g + +// cdb-command:dx int_int +// cdb-check:int_int [Type: generic_struct::AGenericStruct] +// cdb-check:[...]key : 0 [Type: int] +// cdb-check:[...]value : 1 [Type: int] +// cdb-command:dx int_float +// cdb-check:int_float [Type: generic_struct::AGenericStruct] +// cdb-check:[...]key : 2 [Type: int] +// cdb-check:[...]value : 3.500000 [Type: double] +// cdb-command:dx float_int +// cdb-check:float_int [Type: generic_struct::AGenericStruct] +// cdb-check:[...]key : 4.500000 [Type: double] +// cdb-check:[...]value : 5 [Type: int] +// cdb-command:dx float_int_float +// cdb-check:float_int_float [Type: generic_struct::AGenericStruct >] +// cdb-check:[...]key : 6.500000 [Type: double] +// cdb-check:[...]value [Type: generic_struct::AGenericStruct] + #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] diff --git a/src/test/debuginfo/issue-57822.rs b/src/test/debuginfo/issue-57822.rs index 6b2b12edda5d..f6d2146fe11f 100644 --- a/src/test/debuginfo/issue-57822.rs +++ b/src/test/debuginfo/issue-57822.rs @@ -11,20 +11,20 @@ // gdb-command:run // gdb-command:print g -// gdb-check:$1 = issue_57822::main::closure-1 (issue_57822::main::closure-0 (1)) +// gdb-check:$1 = issue_57822::main::{closure#1} (issue_57822::main::{closure#0} (1)) // gdb-command:print b -// gdb-check:$2 = issue_57822::main::generator-3::Unresumed(issue_57822::main::generator-2::Unresumed(2)) +// gdb-check:$2 = issue_57822::main::{generator#3}::Unresumed(issue_57822::main::{generator#2}::Unresumed(2)) // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:print g -// lldbg-check:(issue_57822::main::closure-1) $0 = { 0 = { 0 = 1 } } +// lldbg-check:(issue_57822::main::{closure#1}) $0 = { 0 = { 0 = 1 } } // lldb-command:print b -// lldbg-check:(issue_57822::main::generator-3) $1 = +// lldbg-check:(issue_57822::main::{generator#3}) $1 = #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)] #![omit_gdb_pretty_printer_section] diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs index 550cc66f3899..cf3be2e71967 100644 --- a/src/test/debuginfo/msvc-pretty-enums.rs +++ b/src/test/debuginfo/msvc-pretty-enums.rs @@ -1,5 +1,4 @@ // only-cdb -// ignore-tidy-linelength // compile-flags:-g // cdb-command: g @@ -8,16 +7,16 @@ // so the best we can do is to make sure we are generating the right debuginfo // cdb-command: dx -r2 a,! -// cdb-check:a,! [Type: enum$>, 2, 16, Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$>, 2, 16, Some>::Some] +// cdb-check:a,! [Type: enum$ >, 2, 16, Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$ >, 2, 16, Some>::Some] // cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum] -// cdb-check: [+0x000] discriminant : 0x2 [Type: enum$>, 2, 16, Some>::Discriminant$] +// cdb-check: [+0x000] discriminant : 0x2 [Type: enum$ >, 2, 16, Some>::Discriminant$] // cdb-command: dx -r2 b,! -// cdb-check:b,! [Type: enum$>, 2, 16, Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$>, 2, 16, Some>::Some] +// cdb-check:b,! [Type: enum$ >, 2, 16, Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$ >, 2, 16, Some>::Some] // cdb-check: [+0x000] __0 : 0x11 [Type: msvc_pretty_enums::CStyleEnum] -// cdb-check: [+0x000] discriminant : None (0x11) [Type: enum$>, 2, 16, Some>::Discriminant$] +// cdb-check: [+0x000] discriminant : None (0x11) [Type: enum$ >, 2, 16, Some>::Discriminant$] // cdb-command: dx -r2 c,! // cdb-check:c,! [Type: enum$] @@ -38,24 +37,24 @@ // cdb-check: [+0x000] discriminant : Tag2 (0x13) [Type: enum$::Discriminant$] // cdb-command: dx -r2 f,! -// cdb-check:f,! [Type: enum$, 1, [...], Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$, 1, [...], Some>::Some] +// cdb-check:f,! [Type: enum$ >, 1, [...], Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$ >, 1, [...], Some>::Some] // cdb-check: [+0x000] __0 : 0x[...] : 0x1 [Type: unsigned int *] -// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$, 1, [...], Some>::Discriminant$] +// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$ >, 1, [...], Some>::Discriminant$] // cdb-command: dx -r2 g,! -// cdb-check:g,! [Type: enum$, 1, [...], Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$, 1, [...], Some>::Some] +// cdb-check:g,! [Type: enum$ >, 1, [...], Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$ >, 1, [...], Some>::Some] // cdb-check: [+0x000] __0 : 0x0 [Type: unsigned int *] -// cdb-check: [+0x000] discriminant : None (0x0) [Type: enum$, 1, [...], Some>::Discriminant$] +// cdb-check: [+0x000] discriminant : None (0x0) [Type: enum$ >, 1, [...], Some>::Discriminant$] // cdb-command: dx h -// cdb-check:h : Some [Type: enum$>] +// cdb-check:h : Some [Type: enum$ >] // cdb-check: [+0x000] variant$ : Some (0x1) [Type: core::option::Option] // cdb-check: [+0x004] __0 : 0xc [Type: unsigned int] // cdb-command: dx i -// cdb-check:i : None [Type: enum$>] +// cdb-check:i : None [Type: enum$ >] // cdb-check: [+0x000] variant$ : None (0x0) [Type: core::option::Option] // cdb-command: dx j diff --git a/src/test/debuginfo/mutex.rs b/src/test/debuginfo/mutex.rs index 969099359ab0..40bea30f1252 100644 --- a/src/test/debuginfo/mutex.rs +++ b/src/test/debuginfo/mutex.rs @@ -3,7 +3,6 @@ // cdb-only // min-cdb-version: 10.0.21287.1005 // compile-flags:-g -// ignore-tidy-linelength // === CDB TESTS ================================================================================== // @@ -22,7 +21,7 @@ // // cdb-command:dx lock,d -// cdb-check:lock,d : Ok [Type: enum$, enum$>, 0, 1, Poisoned>>>] +// cdb-check:lock,d : Ok [Type: enum$, enum$ >, 0, 1, Poisoned> > >] // cdb-check: [...] variant$ : Ok (0) [Type: core::result::Result] // cdb-check: [...] __0 [Type: std::sync::mutex::MutexGuard] diff --git a/src/test/debuginfo/pretty-std-collections-hash.rs b/src/test/debuginfo/pretty-std-collections-hash.rs index 7115aec1041a..ede155787125 100644 --- a/src/test/debuginfo/pretty-std-collections-hash.rs +++ b/src/test/debuginfo/pretty-std-collections-hash.rs @@ -77,6 +77,8 @@ // cdb-command: dx hash_map,d // cdb-check: ["0xe"] : 14 [Type: unsigned __int64] +// cdb-command: dx x + #![allow(unused_variables)] use std::collections::HashSet; use std::collections::HashMap; @@ -95,6 +97,9 @@ fn main() { hash_map.insert(i as u64, i as u64); } + let x = &(123u64, 456u64); + let string = "awefawefawe".to_string(); + zzz(); // #break } diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index aeee1e6258de..a7f384c05007 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -1,7 +1,6 @@ // ignore-freebsd: gdb package too new // only-cdb // "Temporarily" ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155 // ignore-android: FIXME(#10381) -// ignore-tidy-linelength // compile-flags:-g // min-gdb-version: 7.7 // min-lldb-version: 310 @@ -72,7 +71,7 @@ // cdb-command: g // cdb-command: dx slice,d -// cdb-check:slice,d : { len=4 } [Type: slice] +// cdb-check:slice,d : { len=4 } [Type: slice$] // cdb-check: [len] : 4 [Type: [...]] // cdb-check: [0] : 0 [Type: int] // cdb-check: [1] : 1 [Type: int] @@ -116,12 +115,12 @@ // NOTE: OsString doesn't have a .natvis entry yet. // cdb-command: dx some -// cdb-check:some : Some [Type: enum$>] +// cdb-check:some : Some [Type: enum$ >] // cdb-check: [...] variant$ : Some (0x1) [Type: core::option::Option] // cdb-check: [...] __0 : 8 [Type: short] // cdb-command: dx none -// cdb-check:none : None [Type: enum$>] +// cdb-check:none : None [Type: enum$ >] // cdb-check: [...] variant$ : None (0x0) [Type: core::option::Option] // cdb-command: dx some_string diff --git a/src/test/debuginfo/rc_arc.rs b/src/test/debuginfo/rc_arc.rs index 9f1e856ab42e..6e558bd3c13a 100644 --- a/src/test/debuginfo/rc_arc.rs +++ b/src/test/debuginfo/rc_arc.rs @@ -1,6 +1,5 @@ // pretty-printers are not loaded // compile-flags:-g -// ignore-tidy-linelength // min-gdb-version: 8.1 // min-cdb-version: 10.0.18317.1001 @@ -36,7 +35,7 @@ // cdb-command:dx w1,d // cdb-check:w1,d [Type: alloc::rc::Weak] -// cdb-check: [...] ptr : [...] [Type: core::ptr::non_null::NonNull>] +// cdb-check: [...] ptr : [...] [Type: core::ptr::non_null::NonNull >] // cdb-command:dx a,d // cdb-check:a,d : 42 [Type: alloc::sync::Arc] diff --git a/src/test/debuginfo/result-types.rs b/src/test/debuginfo/result-types.rs index 18eae7f301fb..a075c437c463 100644 --- a/src/test/debuginfo/result-types.rs +++ b/src/test/debuginfo/result-types.rs @@ -7,11 +7,11 @@ // cdb-command: g // cdb-command: dx x,d -// cdb-check:x,d : Ok [Type: enum$>] +// cdb-check:x,d : Ok [Type: enum$ >] // cdb-check: [...] __0 : -3 [Type: int] // cdb-command: dx y -// cdb-check:y : Err [Type: enum$>] +// cdb-check:y : Err [Type: enum$ >] // cdb-check: [...] __0 : "Some error message" [Type: str] fn main() diff --git a/src/test/debuginfo/simple-tuple.rs b/src/test/debuginfo/simple-tuple.rs index b7fcfeef090a..0807cfedce01 100644 --- a/src/test/debuginfo/simple-tuple.rs +++ b/src/test/debuginfo/simple-tuple.rs @@ -129,38 +129,38 @@ // cdb-command: g // cdb-command:dx noPadding8,d -// cdb-check:noPadding8,d [...]: (-100, 100) [Type: tuple] +// cdb-check:noPadding8,d [...]: (-100, 100) [Type: tuple$] // cdb-check:[...][0] : -100 [Type: [...]] // cdb-check:[...][1] : 100 [Type: [...]] // cdb-command:dx noPadding16,d -// cdb-check:noPadding16,d [...]: (0, 1, 2) [Type: tuple] +// cdb-check:noPadding16,d [...]: (0, 1, 2) [Type: tuple$] // cdb-check:[...][0] : 0 [Type: [...]] // cdb-check:[...][1] : 1 [Type: [...]] // cdb-check:[...][2] : 2 [Type: [...]] // cdb-command:dx noPadding32,d -// cdb-check:noPadding32,d [...]: (3, 4.5[...], 5) [Type: tuple] +// cdb-check:noPadding32,d [...]: (3, 4.5[...], 5) [Type: tuple$] // cdb-check:[...][0] : 3 [Type: [...]] // cdb-check:[...][1] : 4.5[...] [Type: [...]] // cdb-check:[...][2] : 5 [Type: [...]] // cdb-command:dx noPadding64,d -// cdb-check:noPadding64,d [...]: (6, 7.5[...], 8) [Type: tuple] +// cdb-check:noPadding64,d [...]: (6, 7.5[...], 8) [Type: tuple$] // cdb-check:[...][0] : 6 [Type: [...]] // cdb-check:[...][1] : 7.500000 [Type: [...]] // cdb-check:[...][2] : 8 [Type: [...]] // cdb-command:dx internalPadding1,d -// cdb-check:internalPadding1,d [...]: (9, 10) [Type: tuple] +// cdb-check:internalPadding1,d [...]: (9, 10) [Type: tuple$] // cdb-check:[...][0] : 9 [Type: short] // cdb-check:[...][1] : 10 [Type: int] // cdb-command:dx internalPadding2,d -// cdb-check:internalPadding2,d [...]: (11, 12, 13, 14) [Type: tuple] +// cdb-check:internalPadding2,d [...]: (11, 12, 13, 14) [Type: tuple$] // cdb-check:[...][0] : 11 [Type: [...]] // cdb-check:[...][1] : 12 [Type: [...]] // cdb-check:[...][2] : 13 [Type: [...]] // cdb-check:[...][3] : 14 [Type: [...]] // cdb-command:dx paddingAtEnd,d -// cdb-check:paddingAtEnd,d [...]: (15, 16) [Type: tuple] +// cdb-check:paddingAtEnd,d [...]: (15, 16) [Type: tuple$] // cdb-check:[...][0] : 15 [Type: [...]] // cdb-check:[...][1] : 16 [Type: [...]] diff --git a/src/test/debuginfo/thread.rs b/src/test/debuginfo/thread.rs index af35ad6af071..531c37a34211 100644 --- a/src/test/debuginfo/thread.rs +++ b/src/test/debuginfo/thread.rs @@ -9,8 +9,8 @@ // cdb-command:g // // cdb-command:dx join_handle,d -// cdb-check:join_handle,d [Type: std::thread::JoinHandle>] -// cdb-check: [...] __0 [Type: std::thread::JoinInner>] +// cdb-check:join_handle,d [Type: std::thread::JoinHandle >] +// cdb-check: [...] __0 [Type: std::thread::JoinInner >] // // cdb-command:dx t,d // cdb-check:t,d : [...] [Type: std::thread::Thread *] diff --git a/src/test/debuginfo/tuple-in-tuple.rs b/src/test/debuginfo/tuple-in-tuple.rs index 0447d8e9ddeb..578db74e9eeb 100644 --- a/src/test/debuginfo/tuple-in-tuple.rs +++ b/src/test/debuginfo/tuple-in-tuple.rs @@ -65,64 +65,64 @@ // cdb-command: g // cdb-command:dx no_padding1,d -// cdb-check:no_padding1,d [...]: ((0, 1), 2, 3) [Type: tuple, u32, u32>] -// cdb-check:[...][0] : (0, 1) [Type: tuple] +// cdb-check:no_padding1,d [...]: ((0, 1), 2, 3) [Type: tuple$,u32,u32>] +// cdb-check:[...][0] : (0, 1) [Type: tuple$] // cdb-check:[...][1] : 2 [Type: [...]] // cdb-check:[...][2] : 3 [Type: [...]] // cdb-command:dx no_padding1.__0,d -// cdb-check:no_padding1.__0,d [...]: (0, 1) [Type: tuple] +// cdb-check:no_padding1.__0,d [...]: (0, 1) [Type: tuple$] // cdb-check:[...][0] : 0 [Type: [...]] // cdb-check:[...][1] : 1 [Type: [...]] // cdb-command:dx no_padding2,d -// cdb-check:no_padding2,d [...]: (4, (5, 6), 7) [Type: tuple, u32>] +// cdb-check:no_padding2,d [...]: (4, (5, 6), 7) [Type: tuple$,u32>] // cdb-check:[...][0] : 4 [Type: [...]] -// cdb-check:[...][1] : (5, 6) [Type: tuple] +// cdb-check:[...][1] : (5, 6) [Type: tuple$] // cdb-check:[...][2] : 7 [Type: [...]] // cdb-command:dx no_padding2.__1,d -// cdb-check:no_padding2.__1,d [...]: (5, 6) [Type: tuple] +// cdb-check:no_padding2.__1,d [...]: (5, 6) [Type: tuple$] // cdb-check:[...][0] : 5 [Type: [...]] // cdb-check:[...][1] : 6 [Type: [...]] // cdb-command:dx no_padding3,d -// cdb-check:no_padding3,d [...]: (8, 9, (10, 11)) [Type: tuple>] +// cdb-check:no_padding3,d [...]: (8, 9, (10, 11)) [Type: tuple$ >] // cdb-check:[...][0] : 8 [Type: [...]] // cdb-check:[...][1] : 9 [Type: [...]] -// cdb-check:[...][2] : (10, 11) [Type: tuple] +// cdb-check:[...][2] : (10, 11) [Type: tuple$] // cdb-command:dx no_padding3.__2,d -// cdb-check:no_padding3.__2,d [...]: (10, 11) [Type: tuple] +// cdb-check:no_padding3.__2,d [...]: (10, 11) [Type: tuple$] // cdb-check:[...][0] : 10 [Type: [...]] // cdb-check:[...][1] : 11 [Type: [...]] // cdb-command:dx internal_padding1,d -// cdb-check:internal_padding1,d [...]: (12, (13, 14)) [Type: tuple>] +// cdb-check:internal_padding1,d [...]: (12, (13, 14)) [Type: tuple$ >] // cdb-check:[...][0] : 12 [Type: [...]] -// cdb-check:[...][1] : (13, 14) [Type: tuple] +// cdb-check:[...][1] : (13, 14) [Type: tuple$] // cdb-command:dx internal_padding1.__1,d -// cdb-check:internal_padding1.__1,d [...]: (13, 14) [Type: tuple] +// cdb-check:internal_padding1.__1,d [...]: (13, 14) [Type: tuple$] // cdb-check:[...][0] : 13 [Type: [...]] // cdb-check:[...][1] : 14 [Type: [...]] // cdb-command:dx internal_padding2,d -// cdb-check:internal_padding2,d [...]: (15, (16, 17)) [Type: tuple>] +// cdb-check:internal_padding2,d [...]: (15, (16, 17)) [Type: tuple$ >] // cdb-check:[...][0] : 15 [Type: [...]] -// cdb-check:[...][1] : (16, 17) [Type: tuple] +// cdb-check:[...][1] : (16, 17) [Type: tuple$] // cdb-command:dx internal_padding2.__1,d -// cdb-check:internal_padding2.__1,d [...]: (16, 17) [Type: tuple] +// cdb-check:internal_padding2.__1,d [...]: (16, 17) [Type: tuple$] // cdb-check:[...][0] : 16 [Type: [...]] // cdb-check:[...][1] : 17 [Type: [...]] // cdb-command:dx padding_at_end1,d -// cdb-check:padding_at_end1,d [...]: (18, (19, 20)) [Type: tuple>] +// cdb-check:padding_at_end1,d [...]: (18, (19, 20)) [Type: tuple$ >] // cdb-check:[...][0] : 18 [Type: [...]] -// cdb-check:[...][1] : (19, 20) [Type: tuple] +// cdb-check:[...][1] : (19, 20) [Type: tuple$] // cdb-command:dx padding_at_end1.__1,d -// cdb-check:padding_at_end1.__1,d [...][Type: tuple] +// cdb-check:padding_at_end1.__1,d [...][Type: tuple$] // cdb-check:[...][0] : 19 [Type: [...]] // cdb-check:[...][1] : 20 [Type: [...]] // cdb-command:dx padding_at_end2,d -// cdb-check:padding_at_end2,d [...]: ((21, 22), 23) [Type: tuple, i32>] -// cdb-check:[...][0] : (21, 22) [Type: tuple] +// cdb-check:padding_at_end2,d [...]: ((21, 22), 23) [Type: tuple$,i32>] +// cdb-check:[...][0] : (21, 22) [Type: tuple$] // cdb-check:[...][1] : 23 [Type: [...]] // cdb-command:dx padding_at_end2.__0,d -// cdb-check:padding_at_end2.__0,d [...]: (21, 22) [Type: tuple] +// cdb-check:padding_at_end2.__0,d [...]: (21, 22) [Type: tuple$] // cdb-check:[...][0] : 21 [Type: [...]] // cdb-check:[...][1] : 22 [Type: [...]] diff --git a/src/test/debuginfo/type-names.cdb.js b/src/test/debuginfo/type-names.cdb.js new file mode 100644 index 000000000000..8f8b20bfaebb --- /dev/null +++ b/src/test/debuginfo/type-names.cdb.js @@ -0,0 +1,17 @@ +// Helper functions for running the type-names.rs test under CDB + +// CDB exposes an "object model" via JavaScript that allows you to inspect debugging info - in this +// case we want to ask the object model for the return and parameter types for a local variable +// that is a function pointer to make sure that we are emitting the function pointer type in such a +// way that CDB understands how to parse it. + +"use strict"; + +function getFunctionDetails(name) +{ + var localVariable = host.currentThread.Stack.Frames[0].LocalVariables[name]; + var functionPointerType = localVariable.targetType.genericArguments[0]; + var functionType = functionPointerType.baseType; + host.diagnostics.debugLog("Return Type: ", functionType.functionReturnType, "\n"); + host.diagnostics.debugLog("Parameter Types: ", functionType.functionParameterTypes, "\n"); +} diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index cc4a4476d160..d1f322fa76cc 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -1,208 +1,268 @@ // ignore-lldb -// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 + +// GDB changed the way that it formatted Foreign types +// min-gdb-version: 9.2 // compile-flags:-g +// === GDB TESTS =================================================================================== + // gdb-command:run // STRUCTS // gdb-command:whatis simple_struct -// gdbg-check:type = struct Struct1 -// gdbr-check:type = type_names::Struct1 +// gdb-check:type = type_names::Struct1 // gdb-command:whatis generic_struct1 -// gdbg-check:type = struct GenericStruct -// gdbr-check:type = type_names::GenericStruct +// gdb-check:type = type_names::GenericStruct // gdb-command:whatis generic_struct2 -// gdbg-check:type = struct GenericStruct usize> -// gdbr-check:type = type_names::GenericStruct usize> +// gdb-check:type = type_names::GenericStruct usize> // gdb-command:whatis mod_struct -// gdbg-check:type = struct Struct2 -// gdbr-check:type = type_names::mod1::Struct2 +// gdb-check:type = type_names::mod1::Struct2 // ENUMS // gdb-command:whatis simple_enum_1 -// gdbg-check:type = union Enum1 -// gdbr-check:type = type_names::Enum1 +// gdb-check:type = type_names::Enum1 // gdb-command:whatis simple_enum_2 -// gdbg-check:type = union Enum1 -// gdbr-check:type = type_names::Enum1 +// gdb-check:type = type_names::Enum1 // gdb-command:whatis simple_enum_3 -// gdbg-check:type = union Enum2 -// gdbr-check:type = type_names::mod1::Enum2 +// gdb-check:type = type_names::mod1::Enum2 // gdb-command:whatis generic_enum_1 -// gdbg-check:type = union Enum3 -// gdbr-check:type = type_names::mod1::mod2::Enum3 +// gdb-check:type = type_names::mod1::mod2::Enum3 // gdb-command:whatis generic_enum_2 -// gdbg-check:type = union Enum3 -// gdbr-check:type = type_names::mod1::mod2::Enum3 +// gdb-check:type = type_names::mod1::mod2::Enum3 // TUPLES // gdb-command:whatis tuple1 -// gdbg-check:type = struct (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) -// gdbr-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) +// gdb-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) // gdb-command:whatis tuple2 -// gdbg-check:type = struct ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) -// gdbr-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) +// gdb-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) // BOX // gdb-command:whatis box1 -// gdbg-check:type = struct (alloc::boxed::Box, i32) -// gdbr-check:type = (alloc::boxed::Box, i32) +// gdb-check:type = (alloc::boxed::Box, i32) // gdb-command:whatis box2 -// gdbg-check:type = struct (alloc::boxed::Box>, i32) -// gdbr-check:type = (alloc::boxed::Box>, i32) +// gdb-check:type = (alloc::boxed::Box, alloc::alloc::Global>, i32) // REFERENCES // gdb-command:whatis ref1 -// gdbg-check:type = struct (&type_names::Struct1, i32) -// gdbr-check:type = (&type_names::Struct1, i32) +// gdb-check:type = (&type_names::Struct1, i32) // gdb-command:whatis ref2 -// gdbg-check:type = struct (&type_names::GenericStruct, i32) -// gdbr-check:type = (&type_names::GenericStruct, i32) +// gdb-check:type = (&type_names::GenericStruct, i32) // gdb-command:whatis mut_ref1 -// gdbg-check:type = struct (&mut type_names::Struct1, i32) -// gdbr-check:type = (&mut type_names::Struct1, i32) +// gdb-check:type = (&mut type_names::Struct1, i32) // gdb-command:whatis mut_ref2 -// gdbg-check:type = struct (&mut type_names::GenericStruct, i32) -// gdbr-check:type = (&mut type_names::GenericStruct, i32) +// gdb-check:type = (&mut type_names::GenericStruct, i32) // RAW POINTERS // gdb-command:whatis mut_ptr1 -// gdbg-check:type = struct (*mut type_names::Struct1, isize) -// gdbr-check:type = (*mut type_names::Struct1, isize) +// gdb-check:type = (*mut type_names::Struct1, isize) // gdb-command:whatis mut_ptr2 -// gdbg-check:type = struct (*mut isize, isize) -// gdbr-check:type = (*mut isize, isize) +// gdb-check:type = (*mut isize, isize) // gdb-command:whatis mut_ptr3 -// gdbg-check:type = struct (*mut type_names::mod1::mod2::Enum3, isize) -// gdbr-check:type = (*mut type_names::mod1::mod2::Enum3, isize) +// gdb-check:type = (*mut type_names::mod1::mod2::Enum3, isize) // gdb-command:whatis const_ptr1 -// gdbg-check:type = struct (*const type_names::Struct1, isize) -// gdbr-check:type = (*const type_names::Struct1, isize) +// gdb-check:type = (*const type_names::Struct1, isize) // gdb-command:whatis const_ptr2 -// gdbg-check:type = struct (*const isize, isize) -// gdbr-check:type = (*const isize, isize) +// gdb-check:type = (*const isize, isize) // gdb-command:whatis const_ptr3 -// gdbg-check:type = struct (*const type_names::mod1::mod2::Enum3, isize) -// gdbr-check:type = (*const type_names::mod1::mod2::Enum3, isize) +// gdb-check:type = (*const type_names::mod1::mod2::Enum3, isize) // VECTORS // gdb-command:whatis fixed_size_vec1 -// gdbg-check:type = struct ([type_names::Struct1; 3], i16) -// gdbr-check:type = ([type_names::Struct1; 3], i16) +// gdb-check:type = ([type_names::Struct1; 3], i16) // gdb-command:whatis fixed_size_vec2 -// gdbg-check:type = struct ([usize; 3], i16) -// gdbr-check:type = ([usize; 3], i16) +// gdb-check:type = ([usize; 3], i16) // gdb-command:whatis slice1 -// gdbg-check:type = struct &[usize] -// gdbr-check:type = &[usize] +// gdb-check:type = &[usize] // gdb-command:whatis slice2 -// gdbg-check:type = struct &[type_names::mod1::Enum2] -// gdbr-check:type = &[type_names::mod1::Enum2] +// gdb-check:type = &[type_names::mod1::Enum2] // TRAITS // gdb-command:whatis box_trait -// gdbg-check:type = struct Box -// gdbr-check:type = type_names::Box +// gdb-check:type = alloc::boxed::Box // gdb-command:whatis ref_trait -// gdbg-check:type = struct &Trait1 -// gdbr-check:type = type_names::&Trait1 +// gdb-check:type = &dyn type_names::Trait1 // gdb-command:whatis mut_ref_trait -// gdbg-check:type = struct &mut Trait1 -// gdbr-check:type = type_names::&mut Trait1 +// gdb-check:type = &mut dyn type_names::Trait1 // gdb-command:whatis generic_box_trait -// gdbg-check:type = struct Box> -// gdbr-check:type = type_names::Box> +// gdb-check:type = alloc::boxed::Box, alloc::alloc::Global> // gdb-command:whatis generic_ref_trait -// gdbg-check:type = struct &Trait2 -// gdbr-check:type = type_names::&Trait2 +// gdb-check:type = &dyn type_names::Trait2 // gdb-command:whatis generic_mut_ref_trait -// gdbg-check:type = struct &mut Trait2> -// gdbr-check:type = type_names::&mut Trait2> +// gdb-check:type = &mut dyn type_names::Trait2> + +// gdb-command:whatis no_principal_trait +// gdb-check:type = alloc::boxed::Box // BARE FUNCTIONS // gdb-command:whatis rust_fn -// gdbg-check:type = struct (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) -// gdbr-check:type = (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) +// gdb-check:type = (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) // gdb-command:whatis extern_c_fn -// gdbg-check:type = struct (extern "C" fn(isize), usize) -// gdbr-check:type = (extern "C" fn(isize), usize) +// gdb-check:type = (extern "C" fn(isize), usize) // gdb-command:whatis unsafe_fn -// gdbg-check:type = struct (unsafe fn(core::result::Result), usize) -// gdbr-check:type = (unsafe fn(core::result::Result), usize) - -// gdb-command:whatis extern_stdcall_fn -// gdbg-check:type = struct (extern "stdcall" fn(), usize) -// gdbr-check:type = (extern "stdcall" fn(), usize) +// gdb-check:type = (unsafe fn(core::result::Result), usize) // gdb-command:whatis rust_fn_with_return_value -// gdbg-check:type = struct (fn(f64) -> usize, usize) -// gdbr-check:type = (fn(f64) -> usize, usize) +// gdb-check:type = (fn(f64) -> usize, usize) // gdb-command:whatis extern_c_fn_with_return_value -// gdbg-check:type = struct (extern "C" fn() -> type_names::Struct1, usize) -// gdbr-check:type = (extern "C" fn() -> type_names::Struct1, usize) +// gdb-check:type = (extern "C" fn() -> type_names::Struct1, usize) // gdb-command:whatis unsafe_fn_with_return_value -// gdbg-check:type = struct (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) -// gdbr-check:type = (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) - -// gdb-command:whatis extern_stdcall_fn_with_return_value -// gdbg-check:type = struct (extern "stdcall" fn(alloc::boxed::Box) -> usize, usize) -// gdbr-check:type = (extern "stdcall" fn(alloc::boxed::Box) -> usize, usize) +// gdb-check:type = (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) // gdb-command:whatis generic_function_int -// gdbg-check:type = struct (fn(isize) -> isize, usize) -// gdbr-check:type = (fn(isize) -> isize, usize) +// gdb-check:type = (fn(isize) -> isize, usize) // gdb-command:whatis generic_function_struct3 -// gdbg-check:type = struct (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) -// gdbr-check:type = (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) +// gdb-check:type = (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) // gdb-command:whatis variadic_function -// gdbg-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize) -// gdbr-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize) +// gdb-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize) // CLOSURES // gdb-command:whatis closure1 -// gdbg-check:type = struct (closure, usize) -// gdbr-check:type = (closure, usize) +// gdb-check:type = (type_names::main::{closure#0}, usize) // gdb-command:whatis closure2 -// gdbg-check:type = struct (closure, usize) -// gdbr-check:type = (closure, usize) +// gdb-check:type = (type_names::main::{closure#1}, usize) + +// FOREIGN TYPES +// gdb-command:whatis foreign1 +// gdb-check:type = *mut ForeignType1 + +// gdb-command:whatis foreign2 +// gdb-check:type = *mut ForeignType2 + +// === CDB TESTS ================================================================================== + +// cdb-command: g + +// STRUCTS +// 0-sized structs appear to be optimized away in some cases, so only check the structs that do +// actually appear. +// cdb-command:dv /t *_struct +// cdb-check:struct type_names::GenericStruct, f64> mut_generic_struct = [...] + +// ENUMS +// cdb-command:dv /t *_enum_* +// cdb-check:union enum$ simple_enum_1 = [...] +// cdb-check:union enum$ simple_enum_2 = [...] +// cdb-check:type_names::mod1::Enum2 simple_enum_3 = [...] +// cdb-check:type_names::mod1::mod2::Enum3 generic_enum_1 = [...] +// cdb-check:type_names::mod1::mod2::Enum3 generic_enum_2 = [...] + +// TUPLES +// cdb-command:dv /t tuple* +// cdb-check:struct tuple$ > > tuple1 = [...] +// cdb-check:struct tuple$,enum$,char> tuple2 = [...] + +// BOX +// cdb-command:dv /t box* +// cdb-check:struct tuple$,i32> box1 = [...] +// cdb-check:struct tuple$ >, alloc::alloc::Global>,i32> box2 = [...] + +// REFERENCES +// cdb-command:dv /t *ref* +// cdb-check:struct tuple$,i32> ref1 = [...] +// cdb-check:struct tuple$ >,i32> ref2 = [...] +// cdb-check:struct tuple$,i32> mut_ref1 = [...] +// cdb-check:struct tuple$, f64> >,i32> mut_ref2 = [...] + +// RAW POINTERS +// cdb-command:dv /t *_ptr* +// cdb-check:struct tuple$,isize> mut_ptr1 = [...] +// cdb-check:struct tuple$,isize> mut_ptr2 = [...] +// cdb-check:struct tuple$ > >,isize> mut_ptr3 = [...] +// cdb-check:struct tuple$,isize> const_ptr1 = [...] +// cdb-check:struct tuple$,isize> const_ptr2 = [...] +// cdb-check:struct tuple$ > >,isize> const_ptr3 = [...] + +// VECTORS +// cdb-command:dv /t *vec* +// cdb-check:struct tuple$,i16> fixed_size_vec1 = [...] +// cdb-check:struct tuple$,i16> fixed_size_vec2 = [...] +// cdb-check:struct alloc::vec::Vec vec1 = [...] +// cdb-check:struct alloc::vec::Vec, alloc::alloc::Global> vec2 = [...] +// cdb-command:dv /t slice* +// cdb-check:struct slice$ slice1 = [...] +// cdb-check:struct slice$ > slice2 = [...] + +// TRAITS +// cdb-command:dv /t *_trait +// cdb-check:struct ref_mut$ > > > generic_mut_ref_trait = [...] +// cdb-check:struct ref$ > > generic_ref_trait = [...] +// cdb-check:struct alloc::boxed::Box >, alloc::alloc::Global> generic_box_trait = [...] +// cdb-check:struct alloc::boxed::Box, alloc::alloc::Global> box_trait = [...] +// cdb-check:struct ref$ > ref_trait = [...] +// cdb-check:struct ref_mut$ > mut_ref_trait = [...] +// cdb-check:struct alloc::boxed::Box, alloc::alloc::Global> no_principal_trait = [...] +// cdb-check:struct ref$ > has_associated_type_trait = struct ref$ > + +// BARE FUNCTIONS +// cdb-command:dv /t *_fn* +// cdb-check:struct tuple$),usize> unsafe_fn_with_return_value = [...] +// cdb-check:struct tuple$ extern_c_fn_with_return_value = [...] +// cdb-check:struct tuple$ rust_fn_with_return_value = [...] +// cdb-check:struct tuple$ >),usize> unsafe_fn = [...] +// cdb-check:struct tuple$ extern_c_fn = [...] +// cdb-check:struct tuple$ >, enum$ >, 1, [...], Some>),usize> rust_fn = [...] +// cdb-command:dv /t *_function* +// cdb-check:struct tuple$, ...),usize> variadic_function = [...] +// cdb-check:struct tuple$ generic_function_struct3 = [...] +// cdb-check:struct tuple$ generic_function_int = [...] +// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn") +// cdb-check:Return Type: void +// cdb-check:Parameter Types: enum$ >,enum$ >, 1, [...], Some> +// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn_with_return_value") +// cdb-check:Return Type: usize +// cdb-check:Parameter Types: f64 +// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("extern_c_fn_with_return_value") +// cdb-check:Return Type: type_names::Struct1 +// cdb-check:Parameter Types: + +// CLOSURES +// cdb-command:dv /t closure* +// cdb-check:struct tuple$ closure2 = [...] +// cdb-check:struct tuple$ closure1 = [...] + +// FOREIGN TYPES +// cdb-command:dv /t foreign* +// cdb-check:struct ForeignType2 * foreign2 = [...] +// cdb-check:struct ForeignType1 * foreign1 = [...] #![feature(box_syntax)] #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] +#![feature(extern_types)] use self::Enum1::{Variant1, Variant2}; use std::marker::PhantomData; @@ -216,6 +276,8 @@ enum Enum1 { Variant2(isize), } +extern { type ForeignType1; } + mod mod1 { pub use self::Enum2::{Variant1, Variant2}; pub struct Struct2; @@ -234,6 +296,8 @@ mod mod1 { Variant2(T), } } + + extern { pub type ForeignType2; } } trait Trait1 { @@ -242,14 +306,20 @@ trait Trait1 { trait Trait2 { fn dummy(&self, _: T1, _: T2) {} } +trait Trait3 { + type AssocType; + fn dummy(&self) {} +} impl Trait1 for isize {} impl Trait2 for isize {} +impl Trait3 for isize { + type AssocType = isize; +} fn rust_fn(_: Option, _: Option<&mod1::Struct2>) {} extern "C" fn extern_c_fn(_: isize) {} unsafe fn unsafe_fn(_: Result) {} -extern "stdcall" fn extern_stdcall_fn() {} fn rust_fn_with_return_value(_: f64) -> usize { 4 @@ -260,9 +330,6 @@ extern "C" fn extern_c_fn_with_return_value() -> Struct1 { unsafe fn unsafe_fn_with_return_value(_: GenericStruct) -> mod1::Struct2 { mod1::Struct2 } -extern "stdcall" fn extern_stdcall_fn_with_return_value(_: Box) -> usize { - 0 -} fn generic_function(x: T) -> T { x @@ -333,28 +400,28 @@ fn main() { let slice2 = &*vec2; // Trait Objects - let box_trait = (box 0_isize) as Box; - let ref_trait = &0_isize as &Trait1; + let box_trait = (box 0_isize) as Box; + let ref_trait = &0_isize as &dyn Trait1; let mut mut_int1 = 0_isize; - let mut_ref_trait = (&mut mut_int1) as &mut Trait1; + let mut_ref_trait = (&mut mut_int1) as &mut dyn Trait1; + let no_principal_trait = (box 0_isize) as Box; + let has_associated_type_trait = &0_isize as &dyn Trait3; - let generic_box_trait = (box 0_isize) as Box>; - let generic_ref_trait = (&0_isize) as &Trait2; + let generic_box_trait = (box 0_isize) as Box>; + let generic_ref_trait = (&0_isize) as &dyn Trait2; let mut generic_mut_ref_trait_impl = 0_isize; let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl) - as &mut Trait2>; + as &mut dyn Trait2>; // Bare Functions let rust_fn = (rust_fn, 0_usize); let extern_c_fn = (extern_c_fn, 0_usize); let unsafe_fn = (unsafe_fn, 0_usize); - let extern_stdcall_fn = (extern_stdcall_fn, 0_usize); let rust_fn_with_return_value = (rust_fn_with_return_value, 0_usize); let extern_c_fn_with_return_value = (extern_c_fn_with_return_value, 0_usize); let unsafe_fn_with_return_value = (unsafe_fn_with_return_value, 0_usize); - let extern_stdcall_fn_with_return_value = (extern_stdcall_fn_with_return_value, 0_usize); let generic_function_int = (generic_function::, 0_usize); let generic_function_struct3 = (generic_function::, 0_usize); @@ -370,6 +437,10 @@ fn main() { let closure1 = (|x: isize| {}, 0_usize); let closure2 = (|x: i8, y: f32| (x as f32) + y, 0_usize); + // Foreign Types + let foreign1 = unsafe{ 0 as *const ForeignType1 }; + let foreign2 = unsafe{ 0 as *const mod1::ForeignType2 }; + zzz(); // #break } diff --git a/src/test/debuginfo/var-captured-in-nested-closure.rs b/src/test/debuginfo/var-captured-in-nested-closure.rs index 695cdc4f41fa..a2778fc6090d 100644 --- a/src/test/debuginfo/var-captured-in-nested-closure.rs +++ b/src/test/debuginfo/var-captured-in-nested-closure.rs @@ -108,7 +108,7 @@ // cdb-command: dx closure_local // cdb-check:closure_local : 8 [Type: [...]] // cdb-command: dx nested_closure -// cdb-check:nested_closure [Type: var_captured_in_nested_closure::main::{{closure}}::closure-0] +// cdb-check:nested_closure [Type: var_captured_in_nested_closure::main::closure$0::closure$0] // cdb-command: g diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 6a1faee1d8e0..49731b2d7dc0 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -778,6 +778,14 @@ impl<'test> TestCx<'test> { script_str.push_str("version\n"); // List CDB (and more) version info in test output script_str.push_str(".nvlist\n"); // List loaded `*.natvis` files, bulk of custom MSVC debug + // If a .js file exists next to the source file being tested, then this is a JavaScript + // debugging extension that needs to be loaded. + let mut js_extension = self.testpaths.file.clone(); + js_extension.set_extension("cdb.js"); + if js_extension.exists() { + script_str.push_str(&format!(".scriptload \"{}\"\n", js_extension.to_string_lossy())); + } + // Set breakpoints on every line that contains the string "#break" let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy(); for line in &breakpoint_lines { @@ -2329,13 +2337,17 @@ impl<'test> TestCx<'test> { // useful flag. // // For now, though… - if let Some(rev) = self.revision { - let prefixes = format!("CHECK,{}", rev); - if self.config.llvm_version.unwrap_or(0) >= 130000 { - filecheck.args(&["--allow-unused-prefixes", "--check-prefixes", &prefixes]); - } else { - filecheck.args(&["--check-prefixes", &prefixes]); - } + let prefix_for_target = + if self.config.target.contains("msvc") { "MSVC" } else { "NONMSVC" }; + let prefixes = if let Some(rev) = self.revision { + format!("CHECK,{},{}", prefix_for_target, rev) + } else { + format!("CHECK,{}", prefix_for_target) + }; + if self.config.llvm_version.unwrap_or(0) >= 130000 { + filecheck.args(&["--allow-unused-prefixes", "--check-prefixes", &prefixes]); + } else { + filecheck.args(&["--check-prefixes", &prefixes]); } self.compose_and_run(filecheck, "", None, None) } diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 3d5f39e8c904..15ed2f7a0a97 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -52,6 +52,7 @@ const ANNOTATIONS_TO_IGNORE: &[&str] = &[ "// error-pattern", "// gdb", "// lldb", + "// cdb", "// normalize-stderr-test", ];