Skip to content

Commit 093b9a2

Browse files
committed
feat: Support templated lambdas
1 parent 3a3126a commit 093b9a2

File tree

2 files changed

+101
-8
lines changed

2 files changed

+101
-8
lines changed

src/ast.rs

Lines changed: 87 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4965,6 +4965,63 @@ impl<'a> Hash for &'a TemplateParam {
49654965
}
49664966
}
49674967

4968+
/// The `<template-param-decl>` production.
4969+
///
4970+
/// ```text
4971+
/// <template-param-decl> ::= Ty # type parameter
4972+
/// ::= Tn <type> # non-type parameter
4973+
/// ::= Tt <template-param-decl>* E # template parameter
4974+
/// ::= Tp <template-param-decl> # parameter pack
4975+
/// ```
4976+
#[derive(Clone, Debug, PartialEq, Eq)]
4977+
pub enum TemplateParamDecl {
4978+
/// Type Parameter (numbered)
4979+
Type(u8),
4980+
}
4981+
4982+
impl Parse for TemplateParamDecl {
4983+
fn parse<'a, 'b>(
4984+
ctx: &'a ParseContext,
4985+
_subs: &'a mut SubstitutionTable,
4986+
input: IndexStr<'b>,
4987+
) -> Result<(TemplateParamDecl, IndexStr<'b>)> {
4988+
try_begin_parse!("TemplateParamDecl", ctx, input);
4989+
4990+
let tail = consume(b"T", input)?;
4991+
4992+
if let Ok(tail) = consume(b"y", tail) {
4993+
// TODO: implement a counter
4994+
return Ok((TemplateParamDecl::Type(0), tail));
4995+
}
4996+
4997+
// TODO: implement other types as well
4998+
Err(error::Error::UnexpectedText)
4999+
}
5000+
}
5001+
5002+
impl<'subs, W> Demangle<'subs, W> for TemplateParamDecl
5003+
where
5004+
W: 'subs + DemangleWrite,
5005+
{
5006+
fn demangle<'prev, 'ctx>(
5007+
&'subs self,
5008+
ctx: &'ctx mut DemangleContext<'subs, W>,
5009+
scope: Option<ArgScopeStack<'prev, 'subs>>,
5010+
) -> fmt::Result {
5011+
let ctx = try_begin_demangle!(self, ctx, scope);
5012+
5013+
match self {
5014+
TemplateParamDecl::Type(n) => {
5015+
write!(ctx, "typename $T")?;
5016+
if *n > 0 {
5017+
write!(ctx, "{}", n - 1)?;
5018+
}
5019+
}
5020+
}
5021+
Ok(())
5022+
}
5023+
}
5024+
49685025
/// The `<template-template-param>` production.
49695026
///
49705027
/// ```text
@@ -6964,7 +7021,7 @@ impl Parse for Discriminator {
69647021
/// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
69657022
/// ```
69667023
#[derive(Clone, Debug, PartialEq, Eq)]
6967-
pub struct ClosureTypeName(LambdaSig, Option<usize>);
7024+
pub struct ClosureTypeName(Vec<TemplateParamDecl>, LambdaSig, Option<usize>);
69687025

69697026
impl Parse for ClosureTypeName {
69707027
fn parse<'a, 'b>(
@@ -6974,7 +7031,13 @@ impl Parse for ClosureTypeName {
69747031
) -> Result<(ClosureTypeName, IndexStr<'b>)> {
69757032
try_begin_parse!("ClosureTypeName", ctx, input);
69767033

6977-
let tail = consume(b"Ul", input)?;
7034+
let mut tail = consume(b"Ul", input)?;
7035+
let mut params = vec![];
7036+
while let Ok(_) = consume(b"T", tail) {
7037+
let (decl, _tail) = TemplateParamDecl::parse(ctx, subs, tail)?;
7038+
params.push(decl);
7039+
tail = _tail;
7040+
}
69787041
let (sig, tail) = LambdaSig::parse(ctx, subs, tail)?;
69797042
let tail = consume(b"E", tail)?;
69807043
let (num, tail) = if let Ok((num, tail)) = parse_number(10, false, tail) {
@@ -6983,7 +7046,7 @@ impl Parse for ClosureTypeName {
69837046
(None, tail)
69847047
};
69857048
let tail = consume(b"_", tail)?;
6986-
Ok((ClosureTypeName(sig, num), tail))
7049+
Ok((ClosureTypeName(params, sig, num), tail))
69877050
}
69887051
}
69897052

@@ -6998,9 +7061,24 @@ where
69987061
) -> fmt::Result {
69997062
let ctx = try_begin_demangle!(self, ctx, scope);
70007063

7001-
write!(ctx, "{{lambda(")?;
7002-
self.0.demangle(ctx, scope)?;
7003-
write!(ctx, ")#{}}}", self.1.map_or(1, |n| n + 2))?;
7064+
// llvm tools format this as:
7065+
// `'lambda'<typename $T, typename $T0>`
7066+
write!(ctx, "{{lambda")?;
7067+
if !self.0.is_empty() {
7068+
write!(ctx, "<")?;
7069+
let mut need_comma = false;
7070+
for arg in &self.0 {
7071+
if need_comma {
7072+
write!(ctx, ", ")?;
7073+
}
7074+
arg.demangle(ctx, scope)?;
7075+
need_comma = true;
7076+
}
7077+
write!(ctx, ">")?;
7078+
}
7079+
write!(ctx, "(")?;
7080+
self.1.demangle(ctx, scope)?;
7081+
write!(ctx, ")#{}}}", self.2.map_or(1, |n| n + 2))?;
70047082
Ok(())
70057083
}
70067084
}
@@ -10391,11 +10469,11 @@ mod tests {
1039110469
assert_parse!(ClosureTypeName {
1039210470
Ok => {
1039310471
b"UlvE_..." => {
10394-
ClosureTypeName(LambdaSig(vec![]), None),
10472+
ClosureTypeName(vec![], LambdaSig(vec![]), None),
1039510473
b"..."
1039610474
}
1039710475
b"UlvE36_..." => {
10398-
ClosureTypeName(LambdaSig(vec![]), Some(36)),
10476+
ClosureTypeName(vec![], LambdaSig(vec![]), Some(36)),
1039910477
b"..."
1040010478
}
1040110479
}
@@ -10919,6 +10997,7 @@ mod tests {
1091910997
b"UllE_..." => {
1092010998
UnqualifiedName::ClosureType(
1092110999
ClosureTypeName(
11000+
vec![],
1092211001
LambdaSig(vec![
1092311002
TypeHandle::Builtin(
1092411003
BuiltinType::Standard(

tests/tests.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,3 +600,17 @@ demangles!(
600600
_ZN4glslL7combineIhLi2EEEDvmlT0_Li4E_T_DvT0__S1_S3_S3_S3_,
601601
"unsigned char __vector((2)*(4)) glsl::combine<unsigned char, 2>(unsigned char __vector(2), unsigned char __vector(2), unsigned char __vector(2), unsigned char __vector(2))"
602602
);
603+
604+
demangles!(
605+
_ZNSt6__ndk110__function6__funcIZN10xxxxxxxxxx20xxxxxxxxxxxxxxxxxxxx11xxxxxxxxxxxIN8xxxxxxxx14xxxxxxxxxxxxxxINS6_INS6_INS5_10xxxxxxxxxxEN14xxxxxxxxxxxxxx23xxxxxxxxxxxxxxxxxxxxxxxEEENS8_21xxxxxxxxxxxxxxxxxxxxxI18xxxxxxxxxxxxxxxxxxEEEE15xxxxxxxxxxxxxxxEESF_EEvRNS5_20xxxxxxxxxxxxxxxxxxxxIT_T0_EENS_8functionIFRS3_PSJ_EEEEUlTyRSI_iE_NS_9allocatorISS_EEFvRNS6_INS6_ISG_SF_EEiEERKiEED0Ev,
606+
"std::__ndk1::__function::__func<void xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx::xxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>(xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>&, std::__ndk1::function<xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx& (xxxxxxxxxxxxxxx*)>)::{lambda<typename $T>(auto:1&, int)#1}, std::__ndk1::allocator<void xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx::xxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>(xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>&, std::__ndk1::function<xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx& (xxxxxxxxxxxxxxx*)>)::{lambda<typename $T>(auto:1&, int)#1}>, void (xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>, int>&, int const&)>::~__func()"
607+
// This does not match llvm-cxxfilt, it should be:
608+
// "std::__ndk1::__function::__func<void xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx::xxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>(xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>&, std::__ndk1::function<xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx& (xxxxxxxxxxxxxxx*)>)::'lambda'<typename $T>(xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>&, int), std::__ndk1::allocator<void xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx::xxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>(xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>&, std::__ndk1::function<xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx& (xxxxxxxxxxxxxxx*)>)::'lambda'<typename $T>(xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>&, int)>, void (xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>, int>&, int const&)>::~__func()"
609+
);
610+
611+
demangles!(
612+
_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,
613+
"std::__ndk1::__function::__func<auto&& xxxxxxxx::xxxxxxxxx<std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx, bool>(std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, bool xxxxxxxxxxxxxxx::*, char const*)::{lambda<typename $T, typename $T>(auto:1&, auto:2&)#1}, std::__ndk1::allocator<auto&& xxxxxxxx::xxxxxxxxx<std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx, bool>(std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, bool xxxxxxxxxxxxxxx::*, char const*)::{lambda<typename $T, typename $T>(auto:1&, auto:2&)#1}>, void (xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx>, bool>&, bool const&)>::__clone(std::__ndk1::__function::__base<void (xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx>, bool>&, bool const&)>*) const"
614+
// This does not match llvm-cxxfilt, it should be:
615+
// "std::__ndk1::__function::__func<auto&& xxxxxxxx::xxxxxxxxx<std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx, bool>(std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, bool xxxxxxxxxxxxxxx::*, char const*)::'lambda'<typename $T, typename $T0>(std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >&, xxxxxxxxxxxxxxx&), std::__ndk1::allocator<auto&& xxxxxxxx::xxxxxxxxx<std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx, bool>(std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, bool xxxxxxxxxxxxxxx::*, char const*)::'lambda'<typename $T, typename $T0>(std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >&, xxxxxxxxxxxxxxx&)>, void (xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx>, bool>&, bool const&)>::__clone(std::__ndk1::__function::__base<void (xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx>, bool>&, bool const&)>*) const"
616+
);

0 commit comments

Comments
 (0)