diff --git a/src/ast.rs b/src/ast.rs index c2dfbbb..0126bfd 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -556,6 +556,8 @@ where // argument pack. is_template_argument_pack: bool, + is_explicit_obj_param: bool, + // Whether to show function parameters. // This must be set to true before calling `demangle` on `Encoding` // unless that call is via the toplevel call to `MangledName::demangle`. @@ -615,6 +617,7 @@ where is_template_prefix: false, is_template_prefix_in_nested_name: false, is_template_argument_pack: false, + is_explicit_obj_param: false, show_params: !options.no_params, show_return_type: !options.no_return_type, show_expression_literal_types: !options.hide_expression_literal_types, @@ -1037,6 +1040,12 @@ where } let mut need_comma = false; + + // Only the first param should have `this`. + if ctx.is_explicit_obj_param { + write!(ctx, "this ")?; + } + for arg in self.iter() { if need_comma { write!(ctx, ", ")?; @@ -1938,6 +1947,9 @@ impl<'a> GetLeafName<'a> for UnscopedTemplateName { /// ```text /// ::= N [] [] E /// ::= N [] [] E +/// ::= N H E +/// ::= N H E + /// ``` #[derive(Clone, Debug, PartialEq, Eq)] pub enum NestedName { @@ -1945,12 +1957,18 @@ pub enum NestedName { Unqualified( CvQualifiers, Option, + Option, PrefixHandle, UnqualifiedName, ), /// A nested template name. The `` are part of the `PrefixHandle`. - Template(CvQualifiers, Option, PrefixHandle), + Template( + CvQualifiers, + Option, + Option, + PrefixHandle, + ), } impl Parse for NestedName { @@ -1963,19 +1981,28 @@ impl Parse for NestedName { let tail = consume(b"N", input)?; - let (cv_qualifiers, tail) = - if let Ok((q, tail)) = try_recurse!(CvQualifiers::parse(ctx, subs, tail)) { - (q, tail) - } else { - (Default::default(), tail) - }; + let (cv_qualifiers, ref_qualifier, explicit_obj_param, tail) = match tail.peek() { + Some(b'H') => { + let (explicit_obj_param, tail) = ExplicitObjectParameter::parse(ctx, subs, tail)?; + (Default::default(), None, Some(explicit_obj_param), tail) + } + _ => { + let (cv_qualifiers, tail) = + if let Ok((q, tail)) = try_recurse!(CvQualifiers::parse(ctx, subs, tail)) { + (q, tail) + } else { + (Default::default(), tail) + }; - let (ref_qualifier, tail) = - if let Ok((r, tail)) = try_recurse!(RefQualifier::parse(ctx, subs, tail)) { - (Some(r), tail) - } else { - (None, tail) - }; + let (ref_qualifier, tail) = + if let Ok((r, tail)) = try_recurse!(RefQualifier::parse(ctx, subs, tail)) { + (Some(r), tail) + } else { + (None, tail) + }; + (cv_qualifiers, ref_qualifier, None, tail) + } + }; let (prefix, tail) = PrefixHandle::parse(ctx, subs, tail)?; let tail = consume(b"E", tail)?; @@ -1988,11 +2015,17 @@ impl Parse for NestedName { match substitutable { Some(&Substitutable::Prefix(Prefix::Nested(ref prefix, ref name))) => Ok(( - NestedName::Unqualified(cv_qualifiers, ref_qualifier, prefix.clone(), name.clone()), + NestedName::Unqualified( + cv_qualifiers, + ref_qualifier, + explicit_obj_param, + prefix.clone(), + name.clone(), + ), tail, )), Some(&Substitutable::Prefix(Prefix::Template(..))) => Ok(( - NestedName::Template(cv_qualifiers, ref_qualifier, prefix), + NestedName::Template(cv_qualifiers, ref_qualifier, explicit_obj_param, prefix), tail, )), _ => Err(error::Error::UnexpectedText), @@ -2017,12 +2050,20 @@ impl NestedName { } } + /// Get the ref-qualifier for this name, if one exists. + pub fn has_explicit_obj_param(&self) -> bool { + match *self { + NestedName::Unqualified(_, _, Some(ref _r), ..) + | NestedName::Template(_, _, Some(ref _r), ..) => true, + _ => false, + } + } // Not public because the prefix means different things for different // variants, and for `::Template` it actually contains part of what // conceptually belongs to ``. fn prefix(&self) -> &PrefixHandle { match *self { - NestedName::Unqualified(_, _, ref p, _) | NestedName::Template(_, _, ref p) => p, + NestedName::Unqualified(_, _, _, ref p, _) | NestedName::Template(_, _, _, ref p) => p, } } } @@ -2039,7 +2080,7 @@ where let ctx = try_begin_demangle!(self, ctx, scope); match *self { - NestedName::Unqualified(_, _, ref p, ref name) => { + NestedName::Unqualified(_, _, _, ref p, ref name) => { ctx.push_demangle_node(DemangleNodeType::NestedName); p.demangle(ctx, scope)?; if name.accepts_double_colon() { @@ -2048,13 +2089,17 @@ where name.demangle(ctx, scope)?; ctx.pop_demangle_node(); } - NestedName::Template(_, _, ref p) => { + NestedName::Template(_, _, _, ref p) => { ctx.is_template_prefix_in_nested_name = true; p.demangle(ctx, scope)?; ctx.is_template_prefix_in_nested_name = false; } } + if self.has_explicit_obj_param() { + ctx.is_explicit_obj_param = true; + } + if let Some(inner) = ctx.pop_inner() { inner.demangle_as_inner(ctx, scope)?; } @@ -2075,7 +2120,7 @@ where impl GetTemplateArgs for NestedName { fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> { match *self { - NestedName::Template(_, _, ref prefix) => prefix.get_template_args(subs), + NestedName::Template(_, _, _, ref prefix) => prefix.get_template_args(subs), _ => None, } } @@ -2084,10 +2129,10 @@ impl GetTemplateArgs for NestedName { impl<'a> GetLeafName<'a> for NestedName { fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option> { match *self { - NestedName::Unqualified(_, _, ref prefix, ref name) => name + NestedName::Unqualified(_, _, _, ref prefix, ref name) => name .get_leaf_name(subs) .or_else(|| prefix.get_leaf_name(subs)), - NestedName::Template(_, _, ref prefix) => prefix.get_leaf_name(subs), + NestedName::Template(_, _, _, ref prefix) => prefix.get_leaf_name(subs), } } } @@ -4018,6 +4063,19 @@ define_vocabulary! { } } +define_vocabulary! { + /// A production. + /// + /// ```text + /// ::= R # & ref-qualifier + /// ::= O # && ref-qualifier + /// ``` + #[derive(Clone, Debug, PartialEq, Eq)] + pub enum ExplicitObjectParameter { + ExplicitObjectParameter(b"H", "this") + } +} + define_vocabulary! { /// A one of the standard variants of the production. /// @@ -8538,6 +8596,7 @@ mod tests { Ok => { b"NS0_3abcE..." => { Name::Nested(NestedName::Unqualified(CvQualifiers::default(), + None, None, PrefixHandle::BackReference(1), UnqualifiedName::Source(SourceName(Identifier { @@ -8660,6 +8719,7 @@ mod tests { const_: true, }, Some(RefQualifier::RValueRef), + None, PrefixHandle::BackReference(0), UnqualifiedName::Source( SourceName(Identifier { @@ -8677,6 +8737,7 @@ mod tests { const_: false, }, Some(RefQualifier::RValueRef), + None, PrefixHandle::BackReference(0), UnqualifiedName::Source( SourceName(Identifier { @@ -8694,6 +8755,7 @@ mod tests { const_: false, }, None, + None, PrefixHandle::BackReference(0), UnqualifiedName::Source( SourceName(Identifier { @@ -8711,6 +8773,7 @@ mod tests { const_: true, }, Some(RefQualifier::RValueRef), + None, PrefixHandle::NonSubstitution(NonSubstitution(0))), b"...", [ @@ -8732,6 +8795,7 @@ mod tests { const_: false, }, Some(RefQualifier::RValueRef), + None, PrefixHandle::NonSubstitution(NonSubstitution(0))), b"...", [ @@ -8753,6 +8817,7 @@ mod tests { const_: false, }, None, + None, PrefixHandle::NonSubstitution(NonSubstitution(0))), b"...", [ diff --git a/tests/tests.rs b/tests/tests.rs index 1eb7b1d..518ed4f 100755 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -617,6 +617,17 @@ demangles!( "deluge::gui::menu_item::MasterTranspose::MenuItem(std::__cxx11::basic_string, std::allocator > const&, std::__cxx11::basic_string, std::allocator > const&)" ); +demangles!(_ZNH1S3fooES_, "S::foo(this S)"); + +demangles!(_ZNH1S3barILi5EiEEvS_T0_, "void S::bar<5, int>(this S, int)"); + +demangles!(_ZNH1S3bazERKS_, "S::baz(this S const&)"); + +demangles!( + _ZZNH2ns3Foo3fooES0_iENH4Foo24foo2EOKS1_, + "ns::Foo::foo(this ns::Foo, int)::Foo2::foo2(this Foo2 const&&)" +); + // This symbol previously ran into some mutual recursion and unbounded growth of the substitution table. // See and #[test]