From aac8a885520854e4b60ea5733b8b06f9e0cc1fcc Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Thu, 24 Jun 2021 10:36:28 -0700 Subject: [PATCH 1/3] Improve debug symbol names to avoid ambiguity and work better with MSVC's debugger There are several cases where names of types and functions in the debug info are either ambiguous, or not helpful, such as including ambiguous placeholders (e.g., `{{impl}}`, `{{closure}}` or `dyn _'`) or dropping qualifications (e.g., for dynamic types). Instead, each debug symbol name should be unique and useful: * Include disambiguators for anonymous `DefPathDataName` (closures and generators), and unify their formatting when used as a path-qualifier vs item being qualified. * Qualify the principal trait for dynamic types. * If there is no principal trait for a dynamic type, emit all other traits instead. * Respect the `qualified` argument when emitting ref and pointer types. * For implementations, emit the disambiguator. * Print const generics when emitting generic parameters or arguments. Additionally, when targeting MSVC, its debugger treats many command arguments as C++ expressions, even when the argument is defined to be a symbol name. As such names in the debug info need to be more C++-like to be parsed correctly: * Avoid characters with special meaning (`#`, `[`, `"`, `+`). * Never start a name with `<` or `{` as this is treated as an operator. * `>>` is always treated as a right-shift, even when parsing generic arguments (so add a space to avoid this). * Emit function declarations using C/C++ style syntax (e.g., leading return type). * Emit arrays as a synthetic `array$` type. * Include a `$` in all synthetic types as this is a legal character for C++, but not Rust (thus we avoid collisions with user types). --- .../src/debuginfo/metadata.rs | 37 +- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 27 +- .../src/debuginfo/namespace.rs | 21 +- .../src/debuginfo/type_names.rs | 346 +++++++++++++----- src/etc/natvis/intrinsic.natvis | 26 +- src/etc/natvis/libstd.natvis | 2 +- src/test/codegen/async-fn-debug-msvc.rs | 2 +- src/test/codegen/async-fn-debug.rs | 2 +- src/test/codegen/fn-impl-trait-self.rs | 3 +- src/test/codegen/generator-debug-msvc.rs | 2 +- src/test/codegen/generator-debug.rs | 2 +- src/test/debuginfo/basic-types.rs | 44 ++- src/test/debuginfo/function-names.rs | 175 +++++++++ src/test/debuginfo/generator-objects.rs | 16 +- src/test/debuginfo/generic-struct.rs | 21 ++ src/test/debuginfo/issue-57822.rs | 8 +- src/test/debuginfo/msvc-pretty-enums.rs | 37 +- src/test/debuginfo/mutex.rs | 3 +- src/test/debuginfo/pretty-std.rs | 10 +- src/test/debuginfo/rc_arc.rs | 3 +- src/test/debuginfo/result-types.rs | 4 +- src/test/debuginfo/simple-tuple.rs | 14 +- src/test/debuginfo/thread.rs | 4 +- src/test/debuginfo/tuple-in-tuple.rs | 42 +-- src/test/debuginfo/type-names.cdb.js | 17 + src/test/debuginfo/type-names.rs | 289 +++++++++------ .../var-captured-in-nested-closure.rs | 2 +- src/tools/compiletest/src/runtest.rs | 26 +- src/tools/tidy/src/style.rs | 1 + 29 files changed, 842 insertions(+), 344 deletions(-) create mode 100644 src/test/debuginfo/function-names.rs create mode 100644 src/test/debuginfo/type-names.cdb.js diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 1e70664e64d70..0e42931b29a97 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 2b99a2ebad979..8375d4c7ca561 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 9945d4f428259..1cbf538699608 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 7b4b0821c4be8..2684335d73d1b 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,12 +69,12 @@ 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('('); } @@ -70,54 +89,79 @@ pub fn push_debuginfo_type_name<'tcx>( } 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 +169,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 +249,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()); - output.push_str("fn("); + 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("); + } - 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 +299,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 +315,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 +378,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 +386,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_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; - fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) { - if qualified { + 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 89280149a0351..cf887ffb0c01e 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 2c05f9d7c12e5..3ccd2e9c30ed5 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 e410180bfff6f..8efa1b15b3fff 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 7de115f7e9194..39319a3ea722c 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 f9113d50197c1..4bd811bed10e5 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 7edb07d224c36..e2ba4ad30894d 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 8b87a2f064604..ea324695c15d7 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 3721b87678d55..83c7e0e9b6d05 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: __int64] +// 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 : 72 [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 0000000000000..26317f5c3ff32 --- /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 1beed1c835d97..7ac3304aa9634 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 170a610c621c0..c0135de1219d3 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 6b2b12edda5d7..f6d2146fe11fa 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 550cc66f3899c..63555116b94cd 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,61 +7,61 @@ // 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,! : Some({...}) [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,! : None [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$] +// cdb-check:c,! : Tag1 [Type: enum$] // cdb-check: [+0x000] dataful_variant [Type: enum$::Data] // cdb-check: [+0x000] my_data : 0x11 [Type: msvc_pretty_enums::CStyleEnum] // cdb-check: [+0x000] discriminant : Tag1 (0x11) [Type: enum$::Discriminant$] // cdb-command: dx -r2 d,! -// cdb-check:d,! [Type: enum$] +// cdb-check:d,! : Data({...}) [Type: enum$] // cdb-check: [+0x000] dataful_variant [Type: enum$::Data] // cdb-check: [+0x000] my_data : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] // cdb-check: [+0x000] discriminant : 0x10 [Type: enum$::Discriminant$] // cdb-command: dx -r2 e,! -// cdb-check:e,! [Type: enum$] +// cdb-check:e,! : Tag2 [Type: enum$] // cdb-check: [+0x000] dataful_variant [Type: enum$::Data] // cdb-check: [+0x000] my_data : 0x13 [Type: msvc_pretty_enums::CStyleEnum] // 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,! : Some({...}) [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,! : None [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 // cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] // cdb-command: dx -r2 k,! -// cdb-check:k,! [Type: enum$, 1, [...], Some>] +// cdb-check:k,! : Some({...}) [Type: enum$, 1, [...], Some>] // cdb-check: [+0x000] dataful_variant [Type: enum$, 1, [...], Some>::Some] // cdb-check: [+0x000] __0 [Type: alloc::string::String] // cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$, 1, [...], Some>::Discriminant$] diff --git a/src/test/debuginfo/mutex.rs b/src/test/debuginfo/mutex.rs index 969099359ab08..40bea30f1252c 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.rs b/src/test/debuginfo/pretty-std.rs index aeee1e6258de6..f36003fbef0a4 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,17 +115,18 @@ // 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 // NOTE: cdb fails to interpret debug info of Option enums on i686. -// cdb-check:some_string [Type: enum$, 1, [...], Some>] +// cdb-check:some_string : Some({...}) [Type: enum$, 1, [...], Some>] +// cdb-check: [...] __0 : "IAMA optional string!" [Type: alloc::string::String] #![allow(unused_variables)] use std::ffi::OsString; diff --git a/src/test/debuginfo/rc_arc.rs b/src/test/debuginfo/rc_arc.rs index 9f1e856ab42ed..6e558bd3c13aa 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 18eae7f301fbb..a075c437c463b 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 b7fcfeef090aa..9f4bf31f2c277 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 af35ad6af0710..531c37a342119 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 0447d8e9ddeb0..fa6c579480ee6 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 0000000000000..8f8b20bfaebbe --- /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 cc4a4476d160e..934ee2b5d6d0c 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 695cdc4f41fa3..a2778fc6090d2 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 6a1faee1d8e09..49731b2d7dc04 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 3d5f39e8c9049..15ed2f7a0a975 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", ]; From 721b622e075f8e36c048fb7f7ee689305c0c6d93 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 1 Jul 2021 14:26:20 -0400 Subject: [PATCH 2/3] Update cdb tests for expected output Also an fix issue with tuple type names where we can't cast to them in natvis (required by the visualizer for `HashMap`) because of peculiarities with the natvis expression evaluator. --- .../src/debuginfo/type_names.rs | 14 ++++- src/test/debuginfo/basic-types.rs | 2 +- src/test/debuginfo/msvc-pretty-enums.rs | 16 +++--- .../debuginfo/pretty-std-collections-hash.rs | 5 ++ src/test/debuginfo/pretty-std.rs | 3 +- src/test/debuginfo/simple-tuple.rs | 14 ++--- src/test/debuginfo/tuple-in-tuple.rs | 42 +++++++-------- src/test/debuginfo/type-names.rs | 54 +++++++++---------- 8 files changed, 82 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 2684335d73d1b..a97c6a6b4429f 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -81,11 +81,21 @@ pub fn push_debuginfo_type_name<'tcx>( 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 { diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs index 83c7e0e9b6d05..57f9a8b86b693 100644 --- a/src/test/debuginfo/basic-types.rs +++ b/src/test/debuginfo/basic-types.rs @@ -129,7 +129,7 @@ // cdb-check:f64 : 3.500000 [Type: double] // cdb-command:.enable_unicode 1 // cdb-command:dx s -// cdb-check:s : 72 [Type: str] +// cdb-check:s : "Hello, World!" [Type: str] #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs index 63555116b94cd..cf3be2e719674 100644 --- a/src/test/debuginfo/msvc-pretty-enums.rs +++ b/src/test/debuginfo/msvc-pretty-enums.rs @@ -7,43 +7,43 @@ // so the best we can do is to make sure we are generating the right debuginfo // cdb-command: dx -r2 a,! -// cdb-check:a,! : Some({...}) [Type: enum$ >, 2, 16, 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-command: dx -r2 b,! -// cdb-check:b,! : None [Type: enum$ >, 2, 16, 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-command: dx -r2 c,! -// cdb-check:c,! : Tag1 [Type: enum$] +// cdb-check:c,! [Type: enum$] // cdb-check: [+0x000] dataful_variant [Type: enum$::Data] // cdb-check: [+0x000] my_data : 0x11 [Type: msvc_pretty_enums::CStyleEnum] // cdb-check: [+0x000] discriminant : Tag1 (0x11) [Type: enum$::Discriminant$] // cdb-command: dx -r2 d,! -// cdb-check:d,! : Data({...}) [Type: enum$] +// cdb-check:d,! [Type: enum$] // cdb-check: [+0x000] dataful_variant [Type: enum$::Data] // cdb-check: [+0x000] my_data : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] // cdb-check: [+0x000] discriminant : 0x10 [Type: enum$::Discriminant$] // cdb-command: dx -r2 e,! -// cdb-check:e,! : Tag2 [Type: enum$] +// cdb-check:e,! [Type: enum$] // cdb-check: [+0x000] dataful_variant [Type: enum$::Data] // cdb-check: [+0x000] my_data : 0x13 [Type: msvc_pretty_enums::CStyleEnum] // cdb-check: [+0x000] discriminant : Tag2 (0x13) [Type: enum$::Discriminant$] // cdb-command: dx -r2 f,! -// cdb-check:f,! : Some({...}) [Type: enum$ >, 1, [...], 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-command: dx -r2 g,! -// cdb-check:g,! : None [Type: enum$ >, 1, [...], 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$] @@ -61,7 +61,7 @@ // cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] // cdb-command: dx -r2 k,! -// cdb-check:k,! : Some({...}) [Type: enum$, 1, [...], Some>] +// cdb-check:k,! [Type: enum$, 1, [...], Some>] // cdb-check: [+0x000] dataful_variant [Type: enum$, 1, [...], Some>::Some] // cdb-check: [+0x000] __0 [Type: alloc::string::String] // cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$, 1, [...], Some>::Discriminant$] diff --git a/src/test/debuginfo/pretty-std-collections-hash.rs b/src/test/debuginfo/pretty-std-collections-hash.rs index 7115aec1041af..ede1557871257 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 f36003fbef0a4..a7f384c05007d 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -125,8 +125,7 @@ // cdb-command: dx some_string // NOTE: cdb fails to interpret debug info of Option enums on i686. -// cdb-check:some_string : Some({...}) [Type: enum$, 1, [...], Some>] -// cdb-check: [...] __0 : "IAMA optional string!" [Type: alloc::string::String] +// cdb-check:some_string [Type: enum$, 1, [...], Some>] #![allow(unused_variables)] use std::ffi::OsString; diff --git a/src/test/debuginfo/simple-tuple.rs b/src/test/debuginfo/simple-tuple.rs index 9f4bf31f2c277..0807cfedce01d 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/tuple-in-tuple.rs b/src/test/debuginfo/tuple-in-tuple.rs index fa6c579480ee6..578db74e9eeb6 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.rs b/src/test/debuginfo/type-names.rs index 934ee2b5d6d0c..d1f322fa76cca 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -181,34 +181,34 @@ // TUPLES // cdb-command:dv /t tuple* -// cdb-check:struct tuple$ > > tuple1 = [...] -// cdb-check:struct tuple$, enum$, char> tuple2 = [...] +// 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 = [...] +// 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 = [...] +// 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 = [...] +// 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 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* @@ -228,16 +228,16 @@ // 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-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-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> @@ -250,8 +250,8 @@ // CLOSURES // cdb-command:dv /t closure* -// cdb-check:struct tuple$ closure2 = [...] -// cdb-check:struct tuple$ closure1 = [...] +// cdb-check:struct tuple$ closure2 = [...] +// cdb-check:struct tuple$ closure1 = [...] // FOREIGN TYPES // cdb-command:dv /t foreign* From c1601dcbc1b4c71a1485bf6f9ff7286a10da40d1 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Fri, 2 Jul 2021 10:31:22 -0400 Subject: [PATCH 3/3] Fix type name difference between i686 and x86_64 for test --- src/test/debuginfo/basic-types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs index 57f9a8b86b693..c35c32554983a 100644 --- a/src/test/debuginfo/basic-types.rs +++ b/src/test/debuginfo/basic-types.rs @@ -103,7 +103,7 @@ // cdb-command:dx b // cdb-check:b : false [Type: bool] // cdb-command:dx i -// cdb-check:i : -1 [Type: __int64] +// cdb-check:i : -1 [Type: [...]] // The variable 'c' doesn't appear for some reason... // cdb-command:dx i8 // cdb-check:i8 : 68 [Type: char]