From a4ff4cb02c7b3c2a43ba1601502d9047805baf06 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 9 Nov 2021 17:26:50 +1300 Subject: [PATCH] Introduce DemangleOptions::simplify_template_parameters() In a debugger, users may input identifiers containing template parameter values and expect some aspects of the identifer (e.g. the exact type of numeric parameters) to be inferred. For example, given "template struct X", the debugger should accept "X<3>" and not just "X<(short)3>". A debugger can make this work by canonicalizing incoming identifiers containing template parameter values into this simplified form. When these identifiers are being produced via cpp_demangle, it is more efficient and more reliable to have cpp_demangle itself produce this simplified form. --- examples/cppfilt.rs | 8 ++++++++ src/ast.rs | 23 ++++++++++++++++------- src/lib.rs | 10 ++++++++++ tests/tests.rs | 18 ++++++++++++++++++ 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/examples/cppfilt.rs b/examples/cppfilt.rs index 22eac09..2731db5 100644 --- a/examples/cppfilt.rs +++ b/examples/cppfilt.rs @@ -100,6 +100,11 @@ fn main() { .long("no-params") .help("Do not display function arguments"), ) + .arg( + Arg::with_name("hide-expression-literal-types") + .long("hide-expression-literal-types") + .help("Hide types in template parameter expression literals"), + ) .arg( Arg::with_name("mangled_names") .multiple(true) @@ -120,6 +125,9 @@ fn main() { if matches.is_present("noparams") { options = options.no_params(); } + if matches.is_present("hide-expression-literal-types") { + options = options.hide_expression_literal_types(); + } if matches.is_present("noreturntype") { options = options.no_return_type(); } diff --git a/src/ast.rs b/src/ast.rs index d05bad6..8820b96 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -553,6 +553,9 @@ where // unless that call is via the toplevel call to `MangledName::demangle`. show_return_type: bool, + // Whether to show types of expression literals. + show_expression_literal_types: bool, + // recursion protection. state: Cell, } @@ -601,6 +604,7 @@ where is_template_argument_pack: false, show_params: !options.no_params, show_return_type: !options.no_return_type, + show_expression_literal_types: !options.hide_expression_literal_types, state: Cell::new(DemangleState { recursion_level: 0 }), } } @@ -6703,13 +6707,16 @@ where start, end, ) => { - write!(ctx, "(")?; - ty.demangle(ctx, scope)?; + if ctx.show_expression_literal_types { + write!(ctx, "(")?; + ty.demangle(ctx, scope)?; + write!(ctx, ")")?; + } let start = if start < end && ctx.input[start] == b'n' { - write!(ctx, ")-[")?; + write!(ctx, "-[")?; start + 1 } else { - write!(ctx, ")[")?; + write!(ctx, "[")?; start }; let s = ::std::str::from_utf8(&ctx.input[start..end]).map_err(|e| { @@ -6725,9 +6732,11 @@ where end, ) => write_literal(ctx, start, end), ExprPrimary::Literal(ref ty, start, end) => { - write!(ctx, "(")?; - ty.demangle(ctx, scope)?; - write!(ctx, ")")?; + if ctx.show_expression_literal_types { + write!(ctx, "(")?; + ty.demangle(ctx, scope)?; + write!(ctx, ")")?; + } write_literal(ctx, start, end) } } diff --git a/src/lib.rs b/src/lib.rs index 9735c5c..1af0eb8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -107,6 +107,7 @@ impl ParseOptions { pub struct DemangleOptions { no_params: bool, no_return_type: bool, + hide_expression_literal_types: bool, recursion_limit: Option, } @@ -128,6 +129,15 @@ impl DemangleOptions { self } + /// Hide type annotations in template value parameters. + /// These are not needed to distinguish template instances + /// so this can make it easier to match user-provided + /// template instance names. + pub fn hide_expression_literal_types(mut self) -> Self { + self.hide_expression_literal_types = true; + self + } + /// Set the limit on recursion depth during the demangling phase. A low /// limit will cause valid symbols to be rejected, but a high limit may /// allow pathological symbols to overflow the stack during demangling. diff --git a/tests/tests.rs b/tests/tests.rs index e418808..7b83a7e 100755 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -93,6 +93,19 @@ macro_rules! demangles_no_param_and_no_return_type { }; } +macro_rules! demangles_simplify_template_parameters { + ( $mangled:ident , $demangled:expr ) => { + demangles_simplify_template_parameters!($mangled, stringify!($mangled), $demangled); + }; + ( $name:ident , $mangled:expr , $demangled:expr ) => { + #[test] + fn $name() { + let options = DemangleOptions::new().hide_expression_literal_types(); + assert_demangles_as($mangled, $demangled, Some(options)); + } + }; +} + macro_rules! demangles_no_return_type { ( $mangled:ident , $demangled:expr ) => { demangles_no_return_type!($mangled, stringify!($mangled), $demangled); @@ -577,3 +590,8 @@ demangles!( _ZNKSt6__ndk112basic_stringIDuNS_11char_traitsIDuEENS_9allocatorIDuEEE5c_strEv, "std::__ndk1::basic_string, std::__ndk1::allocator >::c_str() const" ); + +demangles_simplify_template_parameters!( + _ZN11SmiTagging2ILs4EE13kSmiShiftSizeE, + "SmiTagging2<4>::kSmiShiftSize" +);