// 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);
composite_type_metadata(
cx,
- trait_object_type,
+ trait_object_type.unwrap_or(trait_type),
&trait_type_name[..],
unique_type_id,
member_descriptions,
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;
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
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);
// 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>,
.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)
)
};
// 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;
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()),
msvc_enum_fallback(tcx, t, def, substs, output, visited);
} else {
push_item_name(tcx, def.did, qualified, output);
- push_type_params(tcx, substs, output, visited);
+ push_generic_params_internal(tcx, substs, output, visited);
}
}
ty::Tuple(component_types) => {
if cpp_like_names {
- output.push_str("tuple<");
+ output.push_str("tuple$<");
} else {
output.push('(');
}
for component_type in component_types {
push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited);
- output.push_str(", ");
+ output.push(',');
+
+ // Natvis does not always like having spaces between parts of the type name
+ // and this causes issues when we need to write a typename in natvis, for example
+ // as part of a cast like the `HashMap` visualizer does.
+ if !cpp_like_names {
+ output.push(' ');
+ }
}
if !component_types.is_empty() {
output.pop();
- output.pop();
+
+ if !cpp_like_names {
+ output.pop();
+ }
}
if cpp_like_names {
- output.push('>');
+ push_close_angle_bracket(tcx, output);
} else {
output.push(')');
}
}
ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => {
- if !cpp_like_names {
+ if cpp_like_names {
+ match mutbl {
+ hir::Mutability::Not => output.push_str("ptr_const$<"),
+ hir::Mutability::Mut => output.push_str("ptr_mut$<"),
+ }
+ } else {
output.push('*');
- }
- match mutbl {
- hir::Mutability::Not => output.push_str("const "),
- hir::Mutability::Mut => output.push_str("mut "),
+ match mutbl {
+ hir::Mutability::Not => output.push_str("const "),
+ hir::Mutability::Mut => output.push_str("mut "),
+ }
}
- push_debuginfo_type_name(tcx, inner_type, true, output, visited);
+ push_debuginfo_type_name(tcx, inner_type, qualified, output, visited);
if cpp_like_names {
- output.push('*');
+ push_close_angle_bracket(tcx, output);
}
}
ty::Ref(_, inner_type, mutbl) => {
+ // Slices and `&str` are treated like C++ pointers when computing debug
+ // info for MSVC debugger. However, wrapping these types' names in a synthetic type
+ // causes the .natvis engine for WinDbg to fail to display their data, so we opt these
+ // types out to aid debugging in MSVC.
+ let is_slice_or_str = match *inner_type.kind() {
+ ty::Slice(_) | ty::Str => true,
+ _ => false,
+ };
+
if !cpp_like_names {
output.push('&');
+ output.push_str(mutbl.prefix_str());
+ } else if !is_slice_or_str {
+ match mutbl {
+ hir::Mutability::Not => output.push_str("ref$<"),
+ hir::Mutability::Mut => output.push_str("ref_mut$<"),
+ }
}
- output.push_str(mutbl.prefix_str());
- push_debuginfo_type_name(tcx, inner_type, true, output, visited);
+ push_debuginfo_type_name(tcx, inner_type, qualified, output, visited);
- if cpp_like_names {
- // Slices and `&str` are treated like C++ pointers when computing debug
- // info for MSVC debugger. However, adding '*' at the end of these types' names
- // causes the .natvis engine for WinDbg to fail to display their data, so we opt these
- // types out to aid debugging in MSVC.
- match *inner_type.kind() {
- ty::Slice(_) | ty::Str => {}
- _ => output.push('*'),
- }
+ if cpp_like_names && !is_slice_or_str {
+ push_close_angle_bracket(tcx, output);
}
}
ty::Array(inner_type, len) => {
- output.push('[');
- push_debuginfo_type_name(tcx, inner_type, true, output, visited);
- output.push_str(&format!("; {}", len.eval_usize(tcx, ty::ParamEnv::reveal_all())));
- output.push(']');
+ if cpp_like_names {
+ output.push_str("array$<");
+ push_debuginfo_type_name(tcx, inner_type, true, output, visited);
+ match len.val {
+ ty::ConstKind::Param(param) => write!(output, ",{}>", param.name).unwrap(),
+ _ => write!(output, ",{}>", len.eval_usize(tcx, ty::ParamEnv::reveal_all()))
+ .unwrap(),
+ }
+ } else {
+ output.push('[');
+ push_debuginfo_type_name(tcx, inner_type, true, output, visited);
+ match len.val {
+ ty::ConstKind::Param(param) => write!(output, "; {}]", param.name).unwrap(),
+ _ => write!(output, "; {}]", len.eval_usize(tcx, ty::ParamEnv::reveal_all()))
+ .unwrap(),
+ }
+ }
}
ty::Slice(inner_type) => {
if cpp_like_names {
- output.push_str("slice<");
+ output.push_str("slice$<");
} else {
output.push('[');
}
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(_) => {
// use a dummy string that should make it clear
// that something unusual is going on
if !visited.insert(t) {
- output.push_str("<recursive_type>");
+ output.push_str(if cpp_like_names {
+ "recursive_type$"
+ } else {
+ "<recursive_type>"
+ });
return;
}
- let sig = t.fn_sig(tcx);
- output.push_str(sig.unsafety().prefix_str());
+ let sig =
+ tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), t.fn_sig(tcx));
- let abi = sig.abi();
- if abi != rustc_target::spec::abi::Abi::Rust {
- output.push_str("extern \"");
- output.push_str(abi.name());
- output.push_str("\" ");
- }
+ if cpp_like_names {
+ // Format as a C++ function pointer: return_type (*)(params...)
+ if sig.output().is_unit() {
+ output.push_str("void");
+ } else {
+ push_debuginfo_type_name(tcx, sig.output(), true, output, visited);
+ }
+ output.push_str(" (*)(");
+ } else {
+ output.push_str(sig.unsafety.prefix_str());
+
+ if sig.abi != rustc_target::spec::abi::Abi::Rust {
+ output.push_str("extern \"");
+ output.push_str(sig.abi.name());
+ output.push_str("\" ");
+ }
- output.push_str("fn(");
+ output.push_str("fn(");
+ }
- let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
if !sig.inputs().is_empty() {
for ¶meter_type in sig.inputs() {
push_debuginfo_type_name(tcx, parameter_type, true, output, visited);
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);
}
// 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(_) => {
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();
} else {
output.push_str("enum$<");
push_item_name(tcx, def.did, true, output);
- push_type_params(tcx, substs, output, visited);
- output.push('>');
+ push_generic_params_internal(tcx, substs, output, visited);
+ push_close_angle_bracket(tcx, output);
}
}
+}
+
+pub fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) {
+ let def_key = tcx.def_key(def_id);
+ if qualified {
+ if let Some(parent) = def_key.parent {
+ push_item_name(tcx, DefId { krate: def_id.krate, index: parent }, true, output);
+ output.push_str("::");
+ }
+ }
+
+ push_unqualified_item_name(tcx, def_id, def_key.disambiguated_data, output);
+}
- fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) {
- if qualified {
+fn push_unqualified_item_name(
+ tcx: TyCtxt<'tcx>,
+ def_id: DefId,
+ disambiguated_data: DisambiguatedDefPathData,
+ output: &mut String,
+) {
+ let cpp_like_names = tcx.sess.target.is_like_msvc;
+
+ match disambiguated_data.data {
+ DefPathData::CrateRoot => {
output.push_str(&tcx.crate_name(def_id.krate).as_str());
- for path_element in tcx.def_path(def_id).data {
- write!(output, "::{}", path_element.data).unwrap();
+ }
+ DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => {
+ // Generators look like closures, but we want to treat them differently
+ // in the debug info.
+ if cpp_like_names {
+ write!(output, "generator${}", disambiguated_data.disambiguator).unwrap();
+ } else {
+ write!(output, "{{generator#{}}}", disambiguated_data.disambiguator).unwrap();
}
- } else {
- output.push_str(&tcx.item_name(def_id).as_str());
}
+ _ => match disambiguated_data.data.name() {
+ DefPathDataName::Named(name) => {
+ output.push_str(&name.as_str());
+ }
+ DefPathDataName::Anon { namespace } => {
+ if cpp_like_names {
+ write!(output, "{}${}", namespace, disambiguated_data.disambiguator).unwrap();
+ } else {
+ write!(output, "{{{}#{}}}", namespace, disambiguated_data.disambiguator)
+ .unwrap();
+ }
+ }
+ },
+ };
+}
+
+// Pushes the generic parameters in the given `InternalSubsts` to the output string.
+// This ignores region parameters, since they can't reliably be
+// reconstructed for items from non-local crates. For local crates, this
+// would be possible but with inlining and LTO we have to use the least
+// common denominator - otherwise we would run into conflicts.
+fn push_generic_params_internal<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ substs: SubstsRef<'tcx>,
+ output: &mut String,
+ visited: &mut FxHashSet<Ty<'tcx>>,
+) {
+ 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<Ty<'tcx>>,
- ) {
- 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('>');
}
</Synthetic>
</Expand>
</Type>
- <Type Name="slice<*>">
+ <Type Name="slice$<*>">
<DisplayString>{{ len={length} }}</DisplayString>
<Expand>
<Item Name="[len]" ExcludeView="simple">length</Item>
</ArrayItems>
</Expand>
</Type>
- <Type Name="tuple<>">
+ <Type Name="tuple$<>">
<DisplayString>()</DisplayString>
</Type>
- <Type Name="tuple<*>">
+ <Type Name="tuple$<*>">
<DisplayString>({__0})</DisplayString>
<Expand>
<Item Name="[0]">__0</Item>
</Expand>
</Type>
- <Type Name="tuple<*,*>">
+ <Type Name="tuple$<*,*>">
<DisplayString>({__0}, {__1})</DisplayString>
<Expand>
<Item Name="[0]">__0</Item>
<Item Name="[1]">__1</Item>
</Expand>
</Type>
- <Type Name="tuple<*,*,*>">
+ <Type Name="tuple$<*,*,*>">
<DisplayString>({__0}, {__1}, {__2})</DisplayString>
<Expand>
<Item Name="[0]">__0</Item>
<Item Name="[2]">__2</Item>
</Expand>
</Type>
- <Type Name="tuple<*,*,*,*>">
+ <Type Name="tuple$<*,*,*,*>">
<DisplayString>({__0}, {__1}, {__2}, {__3})</DisplayString>
<Expand>
<Item Name="[0]">__0</Item>
<Item Name="[3]">__3</Item>
</Expand>
</Type>
- <Type Name="tuple<*,*,*,*,*>">
+ <Type Name="tuple$<*,*,*,*,*>">
<DisplayString>({__0}, {__1}, {__2}, {__3}, {__4})</DisplayString>
<Expand>
<Item Name="[0]">__0</Item>
<Item Name="[4]">__4</Item>
</Expand>
</Type>
- <Type Name="tuple<*,*,*,*,*,*>">
+ <Type Name="tuple$<*,*,*,*,*,*>">
<DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5})</DisplayString>
<Expand>
<Item Name="[0]">__0</Item>
<Item Name="[5]">__5</Item>
</Expand>
</Type>
- <Type Name="tuple<*,*,*,*,*,*,*>">
+ <Type Name="tuple$<*,*,*,*,*,*,*>">
<DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6})</DisplayString>
<Expand>
<Item Name="[0]">__0</Item>
<Item Name="[6]">__6</Item>
</Expand>
</Type>
- <Type Name="tuple<*,*,*,*,*,*,*,*>">
+ <Type Name="tuple$<*,*,*,*,*,*,*,*>">
<DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7})</DisplayString>
<Expand>
<Item Name="[0]">__0</Item>
<Item Name="[7]">__7</Item>
</Expand>
</Type>
- <Type Name="tuple<*,*,*,*,*,*,*,*,*>">
+ <Type Name="tuple$<*,*,*,*,*,*,*,*,*>">
<DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8})</DisplayString>
<Expand>
<Item Name="[0]">__0</Item>
<Item Name="[8]">__8</Item>
</Expand>
</Type>
- <Type Name="tuple<*,*,*,*,*,*,*,*,*,*>">
+ <Type Name="tuple$<*,*,*,*,*,*,*,*,*,*>">
<DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}, {__9})</DisplayString>
<Expand>
<Item Name="[0]">__0</Item>
<Item Name="[9]">__9</Item>
</Expand>
</Type>
- <Type Name="tuple<*,*,*,*,*,*,*,*,*,*,*>">
+ <Type Name="tuple$<*,*,*,*,*,*,*,*,*,*,*>">
<DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}, {__9}, ...)</DisplayString>
<Expand>
<Item Name="[0]">__0</Item>
<If Condition="(base.table.table.ctrl.pointer[i] & 0x80) == 0">
<!-- Bucket is populated -->
<Exec>n--</Exec>
- <Item Name="{((tuple<$T1, $T2>*)base.table.table.ctrl.pointer)[-(i + 1)].__0}">((tuple<$T1, $T2>*)base.table.table.ctrl.pointer)[-(i + 1)].__1</Item>
+ <Item Name="{((tuple$<$T1, $T2>*)base.table.table.ctrl.pointer)[-(i + 1)].__0}">((tuple$<$T1, $T2>*)base.table.table.ctrl.pointer)[-(i + 1)].__1</Item>
</If>
<Exec>i++</Exec>
</Loop>
// 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,
// 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]*]]
// compile-flags: -g
//
// CHECK-LABEL: @main
-// CHECK: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> <recursive_type>",{{.*}}
+// MSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "recursive_type$ (*)()",{{.*}}
+// NONMSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> <recursive_type>",{{.*}}
//
// CHECK: {{.*}}DISubroutineType{{.*}}
// CHECK: {{.*}}DIBasicType(name: "<recur_type>", encoding: DW_ATE_unsigned)
// 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,
// 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]*]]
// 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
// 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 ==================================================================================
// lldbg-check:[...]$12 = 3.5
// lldbr-check:(f64) f64 = 3.5
+
+// === CDB TESTS ===================================================================================
+
+// cdb-command:g
+// cdb-command:dx b
+// cdb-check:b : false [Type: bool]
+// cdb-command:dx i
+// cdb-check:i : -1 [Type: [...]]
+// The variable 'c' doesn't appear for some reason...
+// cdb-command:dx i8
+// cdb-check:i8 : 68 [Type: char]
+// cdb-command:dx i16
+// cdb-check:i16 : -16 [Type: short]
+// cdb-command:dx i32
+// cdb-check:i32 : -32 [Type: int]
+// cdb-command:dx i64
+// cdb-check:i64 : -64 [Type: __int64]
+// cdb-command:dx u
+// cdb-check:u : 0x1 [Type: [...]]
+// cdb-command:dx u8
+// cdb-check:u8 : 0x64 [Type: unsigned char]
+// cdb-command:dx u16
+// cdb-check:u16 : 0x10 [Type: unsigned short]
+// cdb-command:dx u32
+// cdb-check:u32 : 0x20 [Type: unsigned int]
+// cdb-command:dx u64
+// cdb-check:u64 : 0x40 [Type: unsigned __int64]
+// cdb-command:dx f32
+// cdb-check:f32 : 2.500000 [Type: float]
+// cdb-command:dx f64
+// cdb-check:f64 : 3.500000 [Type: double]
+// cdb-command:.enable_unicode 1
+// cdb-command:dx s
+// cdb-check:s : "Hello, World!" [Type: str]
+
#![allow(unused_variables)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
let u64: u64 = 64;
let f32: f32 = 2.5;
let f64: f64 = 3.5;
+ let s: &str = "Hello, World!";
_zzz(); // #break
}
--- /dev/null
+// 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<T1,T2>::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 <function_names::GenericStruct<T,i32> as function_names::TestTrait1>::trait_function();
+// gdb-check:[...]static fn <function_names::GenericStruct<[T; N],f32> as function_names::TestTrait1>::trait_function();
+// gdb-check:[...]static fn <function_names::Mod1::TestStruct2 as function_names::Mod1::TestTrait2>::trait_function();
+// gdb-check:[...]static fn <function_names::TestStruct1 as function_names::TestTrait1>::trait_function();
+
+// Closure
+// gdb-command:info functions -q function_names::.*::{{closure.*
+// gdb-check:[...]static fn function_names::GenericStruct<T1,T2>::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<i32> (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<i32, i32>::impl_function<i32, i32> (void)
+
+// Trait implementations
+// cdb-command:x a!function_names::*::trait_function*
+// cdb-check:[...] a!function_names::impl$6::trait_function<i32, 0x1> (void)
+// cdb-check:[...] a!function_names::impl$3::trait_function<i32> (void)
+// cdb-check:[...] a!function_names::impl$1::trait_function (void)
+// cdb-check:[...] a!function_names::impl$5::trait_function3<function_names::TestStruct1> (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<i32> (void)
+// cdb-check:[...] a!function_names::impl$2::impl_function::closure$0<i32, i32> (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::<i32, i32>::impl_function();
+
+ // Trait implementations
+ TestStruct1::trait_function();
+ Mod1::TestStruct2::trait_function();
+ GenericStruct::<i32, i32>::trait_function();
+ GenericStruct::<[i32; 1], f32>::trait_function();
+ GenericStruct::<TestStruct1, usize>::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<T1, T2>(std::marker::PhantomData<(T1, T2)>);
+
+// Generic implementation
+impl<T1, T2> GenericStruct<T1, T2> {
+ pub fn impl_function() {
+ // Closure in a generic implementation
+ let closure = || { TestStruct1 };
+ closure();
+ }
+}
+
+// Generic trait implementation
+impl<T> TestTrait1 for GenericStruct<T, i32> {
+ 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<T: TestTrait3> TestTrait3 for GenericStruct<T, T::AssocType> {
+ type AssocType = T::AssocType;
+ fn trait_function3() {}
+}
+
+// Generic trait implementation with const generics
+impl<T, const N: usize> TestTrait1 for GenericStruct<[T; N], f32> {
+ fn trait_function() {}
+}
+
+// Generic function
+fn generic_func<T>(value: T) -> T {
+ // Closure in a generic function
+ let closure = || { TestStruct1 };
+ closure();
+
+ value
+}
// 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]
// lldbg-check:[...]$3 = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } }
// lldbr-check:(generic_struct::AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>>) float_int_float = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } }
+// === CDB TESTS ===================================================================================
+
+// cdb-command:g
+
+// cdb-command:dx int_int
+// cdb-check:int_int [Type: generic_struct::AGenericStruct<i32, i32>]
+// 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<i32, f64>]
+// 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<f64, i32>]
+// 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<f64, generic_struct::AGenericStruct<i32, f64> >]
+// cdb-check:[...]key : 6.500000 [Type: double]
+// cdb-check:[...]value [Type: generic_struct::AGenericStruct<i32, f64>]
+
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
// 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]
// only-cdb
-// ignore-tidy-linelength
// compile-flags:-g
// cdb-command: g
// 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$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>]
-// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Some]
+// cdb-check:a,! [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
+// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Some]
// cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check: [+0x000] discriminant : 0x2 [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Discriminant$]
+// cdb-check: [+0x000] discriminant : 0x2 [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Discriminant$]
// cdb-command: dx -r2 b,!
-// cdb-check:b,! [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>]
-// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Some]
+// cdb-check:b,! [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
+// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Some]
// cdb-check: [+0x000] __0 : 0x11 [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check: [+0x000] discriminant : None (0x11) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Discriminant$]
+// cdb-check: [+0x000] discriminant : None (0x11) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Discriminant$]
// cdb-command: dx -r2 c,!
// cdb-check:c,! [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
// cdb-check: [+0x000] discriminant : Tag2 (0x13) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
// cdb-command: dx -r2 f,!
-// cdb-check:f,! [Type: enum$<core::option::Option<u32*>, 1, [...], Some>]
-// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Some]
+// cdb-check:f,! [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
+// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Some]
// cdb-check: [+0x000] __0 : 0x[...] : 0x1 [Type: unsigned int *]
-// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Discriminant$]
+// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$]
// cdb-command: dx -r2 g,!
-// cdb-check:g,! [Type: enum$<core::option::Option<u32*>, 1, [...], Some>]
-// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Some]
+// cdb-check:g,! [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
+// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Some]
// cdb-check: [+0x000] __0 : 0x0 [Type: unsigned int *]
-// cdb-check: [+0x000] discriminant : None (0x0) [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Discriminant$]
+// cdb-check: [+0x000] discriminant : None (0x0) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$]
// cdb-command: dx h
-// cdb-check:h : Some [Type: enum$<core::option::Option<u32>>]
+// cdb-check:h : Some [Type: enum$<core::option::Option<u32> >]
// 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$<core::option::Option<u32>>]
+// cdb-check:i : None [Type: enum$<core::option::Option<u32> >]
// cdb-check: [+0x000] variant$ : None (0x0) [Type: core::option::Option]
// cdb-command: dx j
// cdb-only
// min-cdb-version: 10.0.21287.1005
// compile-flags:-g
-// ignore-tidy-linelength
// === CDB TESTS ==================================================================================
//
//
// cdb-command:dx lock,d
-// cdb-check:lock,d : Ok [Type: enum$<core::result::Result<std::sync::mutex::MutexGuard<i32>, enum$<std::sync::poison::TryLockError<std::sync::mutex::MutexGuard<i32>>, 0, 1, Poisoned>>>]
+// cdb-check:lock,d : Ok [Type: enum$<core::result::Result<std::sync::mutex::MutexGuard<i32>, enum$<std::sync::poison::TryLockError<std::sync::mutex::MutexGuard<i32> >, 0, 1, Poisoned> > >]
// cdb-check: [...] variant$ : Ok (0) [Type: core::result::Result]
// cdb-check: [...] __0 [Type: std::sync::mutex::MutexGuard<i32>]
// 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;
hash_map.insert(i as u64, i as u64);
}
+ let x = &(123u64, 456u64);
+ let string = "awefawefawe".to_string();
+
zzz(); // #break
}
// 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
// cdb-command: g
// cdb-command: dx slice,d
-// cdb-check:slice,d : { len=4 } [Type: slice<i32>]
+// cdb-check:slice,d : { len=4 } [Type: slice$<i32>]
// cdb-check: [len] : 4 [Type: [...]]
// cdb-check: [0] : 0 [Type: int]
// cdb-check: [1] : 1 [Type: int]
// NOTE: OsString doesn't have a .natvis entry yet.
// cdb-command: dx some
-// cdb-check:some : Some [Type: enum$<core::option::Option<i16>>]
+// cdb-check:some : Some [Type: enum$<core::option::Option<i16> >]
// 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$<core::option::Option<i64>>]
+// cdb-check:none : None [Type: enum$<core::option::Option<i64> >]
// cdb-check: [...] variant$ : None (0x0) [Type: core::option::Option]
// cdb-command: dx some_string
// pretty-printers are not loaded
// compile-flags:-g
-// ignore-tidy-linelength
// min-gdb-version: 8.1
// min-cdb-version: 10.0.18317.1001
// cdb-command:dx w1,d
// cdb-check:w1,d [Type: alloc::rc::Weak<i32>]
-// cdb-check: [...] ptr : [...] [Type: core::ptr::non_null::NonNull<alloc::rc::RcBox<i32>>]
+// cdb-check: [...] ptr : [...] [Type: core::ptr::non_null::NonNull<alloc::rc::RcBox<i32> >]
// cdb-command:dx a,d
// cdb-check:a,d : 42 [Type: alloc::sync::Arc<i32>]
// cdb-command: g
// cdb-command: dx x,d
-// cdb-check:x,d : Ok [Type: enum$<core::result::Result<i32, str>>]
+// cdb-check:x,d : Ok [Type: enum$<core::result::Result<i32, str> >]
// cdb-check: [...] __0 : -3 [Type: int]
// cdb-command: dx y
-// cdb-check:y : Err [Type: enum$<core::result::Result<i32, str>>]
+// cdb-check:y : Err [Type: enum$<core::result::Result<i32, str> >]
// cdb-check: [...] __0 : "Some error message" [Type: str]
fn main()
// cdb-command: g
// cdb-command:dx noPadding8,d
-// cdb-check:noPadding8,d [...]: (-100, 100) [Type: tuple<i8, u8>]
+// cdb-check:noPadding8,d [...]: (-100, 100) [Type: tuple$<i8,u8>]
// cdb-check:[...][0] : -100 [Type: [...]]
// cdb-check:[...][1] : 100 [Type: [...]]
// cdb-command:dx noPadding16,d
-// cdb-check:noPadding16,d [...]: (0, 1, 2) [Type: tuple<i16, i16, u16>]
+// cdb-check:noPadding16,d [...]: (0, 1, 2) [Type: tuple$<i16,i16,u16>]
// 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<i32, f32, u32>]
+// cdb-check:noPadding32,d [...]: (3, 4.5[...], 5) [Type: tuple$<i32,f32,u32>]
// 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<i64, f64, u64>]
+// cdb-check:noPadding64,d [...]: (6, 7.5[...], 8) [Type: tuple$<i64,f64,u64>]
// 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<i16, i32>]
+// cdb-check:internalPadding1,d [...]: (9, 10) [Type: tuple$<i16,i32>]
// 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<i16, i32, u32, u64>]
+// cdb-check:internalPadding2,d [...]: (11, 12, 13, 14) [Type: tuple$<i16,i32,u32,u64>]
// 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<i32, i16>]
+// cdb-check:paddingAtEnd,d [...]: (15, 16) [Type: tuple$<i32,i16>]
// cdb-check:[...][0] : 15 [Type: [...]]
// cdb-check:[...][1] : 16 [Type: [...]]
// cdb-command:g
//
// cdb-command:dx join_handle,d
-// cdb-check:join_handle,d [Type: std::thread::JoinHandle<tuple<>>]
-// cdb-check: [...] __0 [Type: std::thread::JoinInner<tuple<>>]
+// cdb-check:join_handle,d [Type: std::thread::JoinHandle<tuple$<> >]
+// cdb-check: [...] __0 [Type: std::thread::JoinInner<tuple$<> >]
//
// cdb-command:dx t,d
// cdb-check:t,d : [...] [Type: std::thread::Thread *]
// cdb-command: g
// cdb-command:dx no_padding1,d
-// cdb-check:no_padding1,d [...]: ((0, 1), 2, 3) [Type: tuple<tuple<u32, u32>, u32, u32>]
-// cdb-check:[...][0] : (0, 1) [Type: tuple<u32, u32>]
+// cdb-check:no_padding1,d [...]: ((0, 1), 2, 3) [Type: tuple$<tuple$<u32,u32>,u32,u32>]
+// cdb-check:[...][0] : (0, 1) [Type: tuple$<u32,u32>]
// 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<u32, u32>]
+// cdb-check:no_padding1.__0,d [...]: (0, 1) [Type: tuple$<u32,u32>]
// 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, tuple<u32, u32>, u32>]
+// cdb-check:no_padding2,d [...]: (4, (5, 6), 7) [Type: tuple$<u32,tuple$<u32,u32>,u32>]
// cdb-check:[...][0] : 4 [Type: [...]]
-// cdb-check:[...][1] : (5, 6) [Type: tuple<u32, u32>]
+// cdb-check:[...][1] : (5, 6) [Type: tuple$<u32,u32>]
// cdb-check:[...][2] : 7 [Type: [...]]
// cdb-command:dx no_padding2.__1,d
-// cdb-check:no_padding2.__1,d [...]: (5, 6) [Type: tuple<u32, u32>]
+// cdb-check:no_padding2.__1,d [...]: (5, 6) [Type: tuple$<u32,u32>]
// 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<u32, u32, tuple<u32, u32>>]
+// cdb-check:no_padding3,d [...]: (8, 9, (10, 11)) [Type: tuple$<u32,u32,tuple$<u32,u32> >]
// cdb-check:[...][0] : 8 [Type: [...]]
// cdb-check:[...][1] : 9 [Type: [...]]
-// cdb-check:[...][2] : (10, 11) [Type: tuple<u32, u32>]
+// cdb-check:[...][2] : (10, 11) [Type: tuple$<u32,u32>]
// cdb-command:dx no_padding3.__2,d
-// cdb-check:no_padding3.__2,d [...]: (10, 11) [Type: tuple<u32, u32>]
+// cdb-check:no_padding3.__2,d [...]: (10, 11) [Type: tuple$<u32,u32>]
// 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<i16, tuple<i32, i32>>]
+// cdb-check:internal_padding1,d [...]: (12, (13, 14)) [Type: tuple$<i16,tuple$<i32,i32> >]
// cdb-check:[...][0] : 12 [Type: [...]]
-// cdb-check:[...][1] : (13, 14) [Type: tuple<i32, i32>]
+// cdb-check:[...][1] : (13, 14) [Type: tuple$<i32,i32>]
// cdb-command:dx internal_padding1.__1,d
-// cdb-check:internal_padding1.__1,d [...]: (13, 14) [Type: tuple<i32, i32>]
+// cdb-check:internal_padding1.__1,d [...]: (13, 14) [Type: tuple$<i32,i32>]
// 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<i16, tuple<i16, i32>>]
+// cdb-check:internal_padding2,d [...]: (15, (16, 17)) [Type: tuple$<i16,tuple$<i16,i32> >]
// cdb-check:[...][0] : 15 [Type: [...]]
-// cdb-check:[...][1] : (16, 17) [Type: tuple<i16, i32>]
+// cdb-check:[...][1] : (16, 17) [Type: tuple$<i16,i32>]
// cdb-command:dx internal_padding2.__1,d
-// cdb-check:internal_padding2.__1,d [...]: (16, 17) [Type: tuple<i16, i32>]
+// cdb-check:internal_padding2.__1,d [...]: (16, 17) [Type: tuple$<i16,i32>]
// 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<i32, tuple<i32, i16>>]
+// cdb-check:padding_at_end1,d [...]: (18, (19, 20)) [Type: tuple$<i32,tuple$<i32,i16> >]
// cdb-check:[...][0] : 18 [Type: [...]]
-// cdb-check:[...][1] : (19, 20) [Type: tuple<i32, i16>]
+// cdb-check:[...][1] : (19, 20) [Type: tuple$<i32,i16>]
// cdb-command:dx padding_at_end1.__1,d
-// cdb-check:padding_at_end1.__1,d [...][Type: tuple<i32, i16>]
+// cdb-check:padding_at_end1.__1,d [...][Type: tuple$<i32,i16>]
// 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<tuple<i32, i16>, i32>]
-// cdb-check:[...][0] : (21, 22) [Type: tuple<i32, i16>]
+// cdb-check:padding_at_end2,d [...]: ((21, 22), 23) [Type: tuple$<tuple$<i32,i16>,i32>]
+// cdb-check:[...][0] : (21, 22) [Type: tuple$<i32,i16>]
// cdb-check:[...][1] : 23 [Type: [...]]
// cdb-command:dx padding_at_end2.__0,d
-// cdb-check:padding_at_end2.__0,d [...]: (21, 22) [Type: tuple<i32, i16>]
+// cdb-check:padding_at_end2.__0,d [...]: (21, 22) [Type: tuple$<i32,i16>]
// cdb-check:[...][0] : 21 [Type: [...]]
// cdb-check:[...][1] : 22 [Type: [...]]
--- /dev/null
+// 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");
+}
// 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<type_names::mod1::Struct2, type_names::mod1::mod2::Struct3>
-// gdbr-check:type = type_names::GenericStruct<type_names::mod1::Struct2, type_names::mod1::mod2::Struct3>
+// gdb-check:type = type_names::GenericStruct<type_names::mod1::Struct2, type_names::mod1::mod2::Struct3>
// gdb-command:whatis generic_struct2
-// gdbg-check:type = struct GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> usize>
-// gdbr-check:type = type_names::GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> usize>
+// gdb-check:type = type_names::GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> 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<type_names::mod1::Struct2>
-// gdbr-check:type = type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>
+// gdb-check:type = type_names::mod1::mod2::Enum3
// gdb-command:whatis generic_enum_2
-// gdbg-check:type = union Enum3<type_names::Struct1>
-// gdbr-check:type = type_names::mod1::mod2::Enum3<type_names::Struct1>
+// 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<type_names::mod1::Struct2>)
-// gdbr-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>)
+// gdb-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>)
// 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<f32>, i32)
-// gdbr-check:type = (alloc::boxed::Box<f32>, i32)
+// gdb-check:type = (alloc::boxed::Box<f32, alloc::alloc::Global>, i32)
// gdb-command:whatis box2
-// gdbg-check:type = struct (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>>, i32)
-// gdbr-check:type = (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>>, i32)
+// gdb-check:type = (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>, 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<char, type_names::Struct1>, i32)
-// gdbr-check:type = (&type_names::GenericStruct<char, type_names::Struct1>, i32)
+// gdb-check:type = (&type_names::GenericStruct<char, type_names::Struct1>, 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<type_names::mod1::Enum2, f64>, i32)
-// gdbr-check:type = (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32)
+// gdb-check:type = (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, 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<type_names::Struct1>, isize)
-// gdbr-check:type = (*mut type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
+// gdb-check:type = (*mut type_names::mod1::mod2::Enum3<type_names::Struct1>, 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<type_names::Struct1>, isize)
-// gdbr-check:type = (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
+// gdb-check:type = (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, 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<Trait1>
-// gdbr-check:type = type_names::Box<Trait1>
+// gdb-check:type = alloc::boxed::Box<dyn type_names::Trait1, alloc::alloc::Global>
// 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<Trait2<i32, type_names::mod1::Struct2>>
-// gdbr-check:type = type_names::Box<Trait2<i32, type_names::mod1::Struct2>>
+// gdb-check:type = alloc::boxed::Box<dyn type_names::Trait2<i32, type_names::mod1::Struct2>, alloc::alloc::Global>
// gdb-command:whatis generic_ref_trait
-// gdbg-check:type = struct &Trait2<type_names::Struct1, type_names::Struct1>
-// gdbr-check:type = type_names::&Trait2<type_names::Struct1, type_names::Struct1>
+// gdb-check:type = &dyn type_names::Trait2<type_names::Struct1, type_names::Struct1>
// gdb-command:whatis generic_mut_ref_trait
-// gdbg-check:type = struct &mut Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
-// gdbr-check:type = type_names::&mut Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
+// gdb-check:type = &mut dyn type_names::Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
+
+// gdb-command:whatis no_principal_trait
+// gdb-check:type = alloc::boxed::Box<dyn core::marker::Send + core::marker::Sync, alloc::alloc::Global>
// BARE FUNCTIONS
// gdb-command:whatis rust_fn
-// gdbg-check:type = struct (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize)
-// gdbr-check:type = (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize)
+// gdb-check:type = (fn(core::option::Option<isize>, 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<char, f64>), usize)
-// gdbr-check:type = (unsafe fn(core::result::Result<char, f64>), 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<char, f64>), 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<u16, u8>) -> type_names::mod1::Struct2, usize)
-// gdbr-check:type = (unsafe fn(type_names::GenericStruct<u16, u8>) -> type_names::mod1::Struct2, usize)
-
-// gdb-command:whatis extern_stdcall_fn_with_return_value
-// gdbg-check:type = struct (extern "stdcall" fn(alloc::boxed::Box<isize>) -> usize, usize)
-// gdbr-check:type = (extern "stdcall" fn(alloc::boxed::Box<isize>) -> usize, usize)
+// gdb-check:type = (unsafe fn(type_names::GenericStruct<u16, u8>) -> 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<enum$<type_names::mod1::Enum2>, f64> mut_generic_struct = [...]
+
+// ENUMS
+// cdb-command:dv /t *_enum_*
+// cdb-check:union enum$<type_names::Enum1> simple_enum_1 = [...]
+// cdb-check:union enum$<type_names::Enum1> 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$<u32,type_names::Struct1,enum$<type_names::mod1::mod2::Enum3<type_names::mod1::Struct2> > > tuple1 = [...]
+// cdb-check:struct tuple$<tuple$<type_names::Struct1,type_names::mod1::mod2::Struct3>,enum$<type_names::mod1::Enum2>,char> tuple2 = [...]
+
+// BOX
+// cdb-command:dv /t box*
+// cdb-check:struct tuple$<alloc::boxed::Box<f32, alloc::alloc::Global>,i32> box1 = [...]
+// cdb-check:struct tuple$<alloc::boxed::Box<enum$<type_names::mod1::mod2::Enum3<f32> >, alloc::alloc::Global>,i32> box2 = [...]
+
+// REFERENCES
+// cdb-command:dv /t *ref*
+// cdb-check:struct tuple$<ref$<type_names::Struct1>,i32> ref1 = [...]
+// cdb-check:struct tuple$<ref$<type_names::GenericStruct<char, type_names::Struct1> >,i32> ref2 = [...]
+// cdb-check:struct tuple$<ref_mut$<type_names::Struct1>,i32> mut_ref1 = [...]
+// cdb-check:struct tuple$<ref_mut$<type_names::GenericStruct<enum$<type_names::mod1::Enum2>, f64> >,i32> mut_ref2 = [...]
+
+// RAW POINTERS
+// cdb-command:dv /t *_ptr*
+// cdb-check:struct tuple$<ptr_mut$<type_names::Struct1>,isize> mut_ptr1 = [...]
+// cdb-check:struct tuple$<ptr_mut$<isize>,isize> mut_ptr2 = [...]
+// cdb-check:struct tuple$<ptr_mut$<enum$<type_names::mod1::mod2::Enum3<type_names::Struct1> > >,isize> mut_ptr3 = [...]
+// cdb-check:struct tuple$<ptr_const$<type_names::Struct1>,isize> const_ptr1 = [...]
+// cdb-check:struct tuple$<ptr_const$<isize>,isize> const_ptr2 = [...]
+// cdb-check:struct tuple$<ptr_const$<enum$<type_names::mod1::mod2::Enum3<type_names::Struct1> > >,isize> const_ptr3 = [...]
+
+// VECTORS
+// cdb-command:dv /t *vec*
+// cdb-check:struct tuple$<array$<type_names::Struct1,3>,i16> fixed_size_vec1 = [...]
+// cdb-check:struct tuple$<array$<usize,3>,i16> fixed_size_vec2 = [...]
+// cdb-check:struct alloc::vec::Vec<usize, alloc::alloc::Global> vec1 = [...]
+// cdb-check:struct alloc::vec::Vec<enum$<type_names::mod1::Enum2>, alloc::alloc::Global> vec2 = [...]
+// cdb-command:dv /t slice*
+// cdb-check:struct slice$<usize> slice1 = [...]
+// cdb-check:struct slice$<enum$<type_names::mod1::Enum2> > slice2 = [...]
+
+// TRAITS
+// cdb-command:dv /t *_trait
+// cdb-check:struct ref_mut$<dyn$<type_names::Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize> > > > generic_mut_ref_trait = [...]
+// cdb-check:struct ref$<dyn$<type_names::Trait2<type_names::Struct1, type_names::Struct1> > > generic_ref_trait = [...]
+// cdb-check:struct alloc::boxed::Box<dyn$<type_names::Trait2<i32, type_names::mod1::Struct2> >, alloc::alloc::Global> generic_box_trait = [...]
+// cdb-check:struct alloc::boxed::Box<dyn$<type_names::Trait1>, alloc::alloc::Global> box_trait = [...]
+// cdb-check:struct ref$<dyn$<type_names::Trait1> > ref_trait = [...]
+// cdb-check:struct ref_mut$<dyn$<type_names::Trait1> > mut_ref_trait = [...]
+// cdb-check:struct alloc::boxed::Box<dyn$<core::marker::Send, core::marker::Sync>, alloc::alloc::Global> no_principal_trait = [...]
+// cdb-check:struct ref$<dyn$<type_names::Trait3> > has_associated_type_trait = struct ref$<dyn$<type_names::Trait3> >
+
+// BARE FUNCTIONS
+// cdb-command:dv /t *_fn*
+// cdb-check:struct tuple$<type_names::mod1::Struct2 (*)(type_names::GenericStruct<u16, u8>),usize> unsafe_fn_with_return_value = [...]
+// cdb-check:struct tuple$<type_names::Struct1 (*)(),usize> extern_c_fn_with_return_value = [...]
+// cdb-check:struct tuple$<usize (*)(f64),usize> rust_fn_with_return_value = [...]
+// cdb-check:struct tuple$<void (*)(enum$<core::result::Result<char, f64> >),usize> unsafe_fn = [...]
+// cdb-check:struct tuple$<void (*)(isize),usize> extern_c_fn = [...]
+// cdb-check:struct tuple$<void (*)(enum$<core::option::Option<isize> >, enum$<core::option::Option<ref$<type_names::mod1::Struct2> >, 1, [...], Some>),usize> rust_fn = [...]
+// cdb-command:dv /t *_function*
+// cdb-check:struct tuple$<isize (*)(ptr_const$<u8>, ...),usize> variadic_function = [...]
+// cdb-check:struct tuple$<type_names::mod1::mod2::Struct3 (*)(type_names::mod1::mod2::Struct3),usize> generic_function_struct3 = [...]
+// cdb-check:struct tuple$<isize (*)(isize),usize> 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$<core::option::Option<isize> >,enum$<core::option::Option<ref$<type_names::mod1::Struct2> >, 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$<type_names::main::closure$1,usize> closure2 = [...]
+// cdb-check:struct tuple$<type_names::main::closure$0,usize> 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;
Variant2(isize),
}
+extern { type ForeignType1; }
+
mod mod1 {
pub use self::Enum2::{Variant1, Variant2};
pub struct Struct2;
Variant2(T),
}
}
+
+ extern { pub type ForeignType2; }
}
trait Trait1 {
trait Trait2<T1, T2> {
fn dummy(&self, _: T1, _: T2) {}
}
+trait Trait3 {
+ type AssocType;
+ fn dummy(&self) {}
+}
impl Trait1 for isize {}
impl<T1, T2> Trait2<T1, T2> for isize {}
+impl Trait3 for isize {
+ type AssocType = isize;
+}
fn rust_fn(_: Option<isize>, _: Option<&mod1::Struct2>) {}
extern "C" fn extern_c_fn(_: isize) {}
unsafe fn unsafe_fn(_: Result<char, f64>) {}
-extern "stdcall" fn extern_stdcall_fn() {}
fn rust_fn_with_return_value(_: f64) -> usize {
4
unsafe fn unsafe_fn_with_return_value(_: GenericStruct<u16, u8>) -> mod1::Struct2 {
mod1::Struct2
}
-extern "stdcall" fn extern_stdcall_fn_with_return_value(_: Box<isize>) -> usize {
- 0
-}
fn generic_function<T>(x: T) -> T {
x
let slice2 = &*vec2;
// Trait Objects
- let box_trait = (box 0_isize) as Box<Trait1>;
- let ref_trait = &0_isize as &Trait1;
+ let box_trait = (box 0_isize) as Box<dyn Trait1>;
+ 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<dyn Send + Sync>;
+ let has_associated_type_trait = &0_isize as &dyn Trait3<AssocType = isize>;
- let generic_box_trait = (box 0_isize) as Box<Trait2<i32, mod1::Struct2>>;
- let generic_ref_trait = (&0_isize) as &Trait2<Struct1, Struct1>;
+ let generic_box_trait = (box 0_isize) as Box<dyn Trait2<i32, mod1::Struct2>>;
+ let generic_ref_trait = (&0_isize) as &dyn Trait2<Struct1, Struct1>;
let mut generic_mut_ref_trait_impl = 0_isize;
let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl)
- as &mut Trait2<mod1::mod2::Struct3, GenericStruct<usize, isize>>;
+ as &mut dyn Trait2<mod1::mod2::Struct3, GenericStruct<usize, isize>>;
// 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::<isize>, 0_usize);
let generic_function_struct3 = (generic_function::<mod1::mod2::Struct3>, 0_usize);
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
}
// 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
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 {
// 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)
}
"// error-pattern",
"// gdb",
"// lldb",
+ "// cdb",
"// normalize-stderr-test",
];