diff --git a/src/ast.rs b/src/ast.rs index c9d68cd..c56bf09 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -4965,6 +4965,63 @@ impl<'a> Hash for &'a TemplateParam { } } +/// The `` production. +/// +/// ```text +/// ::= Ty # type parameter +/// ::= Tn # non-type parameter +/// ::= Tt * E # template parameter +/// ::= Tp # parameter pack +/// ``` +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum TemplateParamDecl { + /// Type Parameter (numbered) + Type(u8), +} + +impl Parse for TemplateParamDecl { + fn parse<'a, 'b>( + ctx: &'a ParseContext, + _subs: &'a mut SubstitutionTable, + input: IndexStr<'b>, + ) -> Result<(TemplateParamDecl, IndexStr<'b>)> { + try_begin_parse!("TemplateParamDecl", ctx, input); + + let tail = consume(b"T", input)?; + + if let Ok(tail) = consume(b"y", tail) { + // TODO: implement a counter + return Ok((TemplateParamDecl::Type(0), tail)); + } + + // TODO: implement other types as well + Err(error::Error::UnexpectedText) + } +} + +impl<'subs, W> Demangle<'subs, W> for TemplateParamDecl +where + W: 'subs + DemangleWrite, +{ + fn demangle<'prev, 'ctx>( + &'subs self, + ctx: &'ctx mut DemangleContext<'subs, W>, + scope: Option>, + ) -> fmt::Result { + let ctx = try_begin_demangle!(self, ctx, scope); + + match self { + TemplateParamDecl::Type(n) => { + write!(ctx, "typename $T")?; + if *n > 0 { + write!(ctx, "{}", n - 1)?; + } + } + } + Ok(()) + } +} + /// The `` production. /// /// ```text @@ -6964,7 +7021,7 @@ impl Parse for Discriminator { /// ::= Ul E [ ] _ /// ``` #[derive(Clone, Debug, PartialEq, Eq)] -pub struct ClosureTypeName(LambdaSig, Option); +pub struct ClosureTypeName(Vec, LambdaSig, Option); impl Parse for ClosureTypeName { fn parse<'a, 'b>( @@ -6974,7 +7031,13 @@ impl Parse for ClosureTypeName { ) -> Result<(ClosureTypeName, IndexStr<'b>)> { try_begin_parse!("ClosureTypeName", ctx, input); - let tail = consume(b"Ul", input)?; + let mut tail = consume(b"Ul", input)?; + let mut params = vec![]; + while let Ok(_) = consume(b"T", tail) { + let (decl, _tail) = TemplateParamDecl::parse(ctx, subs, tail)?; + params.push(decl); + tail = _tail; + } let (sig, tail) = LambdaSig::parse(ctx, subs, tail)?; let tail = consume(b"E", tail)?; let (num, tail) = if let Ok((num, tail)) = parse_number(10, false, tail) { @@ -6983,7 +7046,7 @@ impl Parse for ClosureTypeName { (None, tail) }; let tail = consume(b"_", tail)?; - Ok((ClosureTypeName(sig, num), tail)) + Ok((ClosureTypeName(params, sig, num), tail)) } } @@ -6998,9 +7061,24 @@ where ) -> fmt::Result { let ctx = try_begin_demangle!(self, ctx, scope); - write!(ctx, "{{lambda(")?; - self.0.demangle(ctx, scope)?; - write!(ctx, ")#{}}}", self.1.map_or(1, |n| n + 2))?; + // llvm tools format this as: + // `'lambda'` + write!(ctx, "{{lambda")?; + if !self.0.is_empty() { + write!(ctx, "<")?; + let mut need_comma = false; + for arg in &self.0 { + if need_comma { + write!(ctx, ", ")?; + } + arg.demangle(ctx, scope)?; + need_comma = true; + } + write!(ctx, ">")?; + } + write!(ctx, "(")?; + self.1.demangle(ctx, scope)?; + write!(ctx, ")#{}}}", self.2.map_or(1, |n| n + 2))?; Ok(()) } } @@ -10391,11 +10469,11 @@ mod tests { assert_parse!(ClosureTypeName { Ok => { b"UlvE_..." => { - ClosureTypeName(LambdaSig(vec![]), None), + ClosureTypeName(vec![], LambdaSig(vec![]), None), b"..." } b"UlvE36_..." => { - ClosureTypeName(LambdaSig(vec![]), Some(36)), + ClosureTypeName(vec![], LambdaSig(vec![]), Some(36)), b"..." } } @@ -10919,6 +10997,7 @@ mod tests { b"UllE_..." => { UnqualifiedName::ClosureType( ClosureTypeName( + vec![], LambdaSig(vec![ TypeHandle::Builtin( BuiltinType::Standard( diff --git a/tests/tests.rs b/tests/tests.rs index 8e908e1..f72fa36 100755 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -600,3 +600,17 @@ demangles!( _ZN4glslL7combineIhLi2EEEDvmlT0_Li4E_T_DvT0__S1_S3_S3_S3_, "unsigned char __vector((2)*(4)) glsl::combine(unsigned char __vector(2), unsigned char __vector(2), unsigned char __vector(2), unsigned char __vector(2))" ); + +demangles!( + _ZNSt6__ndk110__function6__funcIZN10xxxxxxxxxx20xxxxxxxxxxxxxxxxxxxx11xxxxxxxxxxxIN8xxxxxxxx14xxxxxxxxxxxxxxINS6_INS6_INS5_10xxxxxxxxxxEN14xxxxxxxxxxxxxx23xxxxxxxxxxxxxxxxxxxxxxxEEENS8_21xxxxxxxxxxxxxxxxxxxxxI18xxxxxxxxxxxxxxxxxxEEEE15xxxxxxxxxxxxxxxEESF_EEvRNS5_20xxxxxxxxxxxxxxxxxxxxIT_T0_EENS_8functionIFRS3_PSJ_EEEEUlTyRSI_iE_NS_9allocatorISS_EEFvRNS6_INS6_ISG_SF_EEiEERKiEED0Ev, + "std::__ndk1::__function::__func, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>(xxxxxxxx::xxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>&, std::__ndk1::function)::{lambda(auto:1&, int)#1}, std::__ndk1::allocator, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>(xxxxxxxx::xxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>&, std::__ndk1::function)::{lambda(auto:1&, int)#1}>, void (xxxxxxxx::xxxxxxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>, int>&, int const&)>::~__func()" + // This does not match llvm-cxxfilt, it should be: + // "std::__ndk1::__function::__func, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>(xxxxxxxx::xxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>&, std::__ndk1::function)::'lambda'(xxxxxxxx::xxxxxxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx >, xxxxxxxxxxxxxxx>&, int), std::__ndk1::allocator, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>(xxxxxxxx::xxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>&, std::__ndk1::function)::'lambda'(xxxxxxxx::xxxxxxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx >, xxxxxxxxxxxxxxx>&, int)>, void (xxxxxxxx::xxxxxxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>, int>&, int const&)>::~__func()" +); + +demangles!( + _ZNKSt6__ndk110__function6__funcIZN8xxxxxxxx9xxxxxxxxxINS_10shared_ptrINS2_20xxxxxxxxxxxxxxxxxxxxINS2_10xxxxxxxxxxE15xxxxxxxxxxxxxxxEEEES7_bEEODaT_MT0_T1_PKcEUlTyTyRSB_RSC_E_NS_9allocatorISJ_EEFvRNS2_14xxxxxxxxxxxxxxINSM_IS6_S7_EEbEERKbEE7__cloneEPNS0_6__baseISS_EE, + "std::__ndk1::__function::__func >, xxxxxxxxxxxxxxx, bool>(std::__ndk1::shared_ptr >, bool xxxxxxxxxxxxxxx::*, char const*)::{lambda(auto:1&, auto:2&)#1}, std::__ndk1::allocator >, xxxxxxxxxxxxxxx, bool>(std::__ndk1::shared_ptr >, bool xxxxxxxxxxxxxxx::*, char const*)::{lambda(auto:1&, auto:2&)#1}>, void (xxxxxxxx::xxxxxxxxxxxxxx, bool>&, bool const&)>::__clone(std::__ndk1::__function::__base, bool>&, bool const&)>*) const" + // This does not match llvm-cxxfilt, it should be: + // "std::__ndk1::__function::__func >, xxxxxxxxxxxxxxx, bool>(std::__ndk1::shared_ptr >, bool xxxxxxxxxxxxxxx::*, char const*)::'lambda'(std::__ndk1::shared_ptr >&, xxxxxxxxxxxxxxx&), std::__ndk1::allocator >, xxxxxxxxxxxxxxx, bool>(std::__ndk1::shared_ptr >, bool xxxxxxxxxxxxxxx::*, char const*)::'lambda'(std::__ndk1::shared_ptr >&, xxxxxxxxxxxxxxx&)>, void (xxxxxxxx::xxxxxxxxxxxxxx, bool>&, bool const&)>::__clone(std::__ndk1::__function::__base, bool>&, bool const&)>*) const" +);