diff --git a/src/ast.rs b/src/ast.rs index b5c7fe4..5e9cf3b 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -5501,11 +5501,14 @@ where /// The `` production. /// /// ```text -/// ::= Tn # non-type parameter +/// ::= Ty # type parameter +/// ::= Tn # non-type parameter /// ::= Tp # parameter pack /// ``` #[derive(Clone, Debug, PartialEq, Eq)] pub enum TemplateParamDecl { + /// A type parameter. + Type(u8), /// A non-type parameter. NonType(TypeHandle), /// A parameter pack. @@ -5521,6 +5524,10 @@ impl Parse for TemplateParamDecl { try_begin_parse!("TemplateParamDecl", ctx, input); let input = consume(b"T", input)?; + if let Ok(tail) = consume(b"y", input) { + return Ok((TemplateParamDecl::Type(0), tail)); + } + if let Ok(tail) = consume(b"n", input) { let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?; return Ok((TemplateParamDecl::NonType(ty), tail)); @@ -5547,6 +5554,13 @@ where 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(()) + } TemplateParamDecl::NonType(ref ty) => ty.demangle(ctx, scope), TemplateParamDecl::ParameterPack(ref pack) => pack.demangle(ctx, scope), } @@ -7588,10 +7602,10 @@ impl Parse for Discriminator { /// The `` production. /// /// ```text -/// ::= Ul E [ ] _ +/// ::= 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>( @@ -7601,7 +7615,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 tail.peek() == Some(b'T') && !matches!(tail.peek_second(), Some(b'_' | b'0'..=b'9')) { + 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) { @@ -7610,7 +7630,7 @@ impl Parse for ClosureTypeName { (None, tail) }; let tail = consume(b"_", tail)?; - Ok((ClosureTypeName(sig, num), tail)) + Ok((ClosureTypeName(params, sig, num), tail)) } } @@ -7625,9 +7645,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(()) } } @@ -10275,6 +10310,14 @@ mod tests { b"...", [] } + b"TyS_..." => { + TemplateArg::ParamDecl( + TemplateParamDecl::Type(0), + Box::new(TemplateArg::Type(TypeHandle::BackReference(0))) + ), + b"...", + [] + } } Err => { b"..." => Error::UnexpectedText, @@ -10282,10 +10325,10 @@ mod tests { b"J..." => Error::UnexpectedText, b"JS_..." => Error::UnexpectedText, // s that we don't implement yet. - b"Ty" => Error::UnexpectedText, b"Tk" => Error::UnexpectedText, b"Tt" => Error::UnexpectedText, b"Tp" => Error::UnexpectedText, + b"Ty" => Error::UnexpectedEnd, b"JS_" => Error::UnexpectedEnd, b"X" => Error::UnexpectedEnd, b"J" => Error::UnexpectedEnd, @@ -11476,11 +11519,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"..." } } @@ -12082,6 +12125,7 @@ mod tests { b"UllE_..." => { UnqualifiedName::ClosureType( ClosureTypeName( + vec![], LambdaSig(vec![ TypeHandle::Builtin( BuiltinType::Standard( @@ -12176,6 +12220,7 @@ mod tests { b"UllE_B1Q..." => { UnqualifiedName::ClosureType( ClosureTypeName( + vec![], LambdaSig(vec![ TypeHandle::Builtin( BuiltinType::Standard( diff --git a/tests/tests.rs b/tests/tests.rs index e782d2c..a9380b4 100755 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -270,6 +270,11 @@ demangles!( ); demangles!(_ZUlvE_, "{lambda()#1}"); +demangles!(_ZUlT_E_, "{lambda(auto:1)#1}"); +demangles!(_ZUlT0_E_, "{lambda(auto:2)#1}"); +demangles!(_ZUlTyT_E_, "{lambda(auto:1)#1}"); +demangles!(_ZUlTnivE_, "{lambda()#1}"); +demangles!(_ZUlTpTyvE_, "{lambda()#1}"); demangles!(_ZZ3aaavEUlvE_, "aaa()::{lambda()#1}"); demangles!(_ZZ3aaavENUlvE_3bbbE, "aaa()::{lambda()#1}::bbb"); demangles!(_ZN3aaaUlvE_D1Ev, "aaa::{lambda()#1}::~{lambda()#1}()"); @@ -733,3 +738,16 @@ fn test_pathological_recursion() { } } } +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" +);