Skip to content

Commit

Permalink
feat: Support templated lambdas
Browse files Browse the repository at this point in the history
  • Loading branch information
Swatinem committed Feb 10, 2022
1 parent 3a3126a commit 093b9a2
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 8 deletions.
95 changes: 87 additions & 8 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4965,6 +4965,63 @@ impl<'a> Hash for &'a TemplateParam {
}
}

/// The `<template-param-decl>` production.
///
/// ```text
/// <template-param-decl> ::= Ty # type parameter
/// ::= Tn <type> # non-type parameter
/// ::= Tt <template-param-decl>* E # template parameter
/// ::= Tp <template-param-decl> # 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<ArgScopeStack<'prev, 'subs>>,
) -> 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 `<template-template-param>` production.
///
/// ```text
Expand Down Expand Up @@ -6964,7 +7021,7 @@ impl Parse for Discriminator {
/// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
/// ```
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ClosureTypeName(LambdaSig, Option<usize>);
pub struct ClosureTypeName(Vec<TemplateParamDecl>, LambdaSig, Option<usize>);

impl Parse for ClosureTypeName {
fn parse<'a, 'b>(
Expand All @@ -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) {
Expand All @@ -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))
}
}

Expand All @@ -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'<typename $T, typename $T0>`
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(())
}
}
Expand Down Expand Up @@ -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"..."
}
}
Expand Down Expand Up @@ -10919,6 +10997,7 @@ mod tests {
b"UllE_..." => {
UnqualifiedName::ClosureType(
ClosureTypeName(
vec![],
LambdaSig(vec![
TypeHandle::Builtin(
BuiltinType::Standard(
Expand Down
14 changes: 14 additions & 0 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,3 +600,17 @@ demangles!(
_ZN4glslL7combineIhLi2EEEDvmlT0_Li4E_T_DvT0__S1_S3_S3_S3_,
"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))"
);

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<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()"
// This does not match llvm-cxxfilt, it should be:
// "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()"
);

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<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"
// This does not match llvm-cxxfilt, it should be:
// "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"
);

0 comments on commit 093b9a2

Please sign in to comment.