From 2d2bcf5361d223903f6a8dfbd09798aea0e964b4 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Fri, 12 Jul 2019 21:18:51 +0200 Subject: [PATCH] fix and improve empty template parameter pack handling (#41) --- src/lib.rs | 55 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7f334ce..c1d0ad6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1109,7 +1109,7 @@ impl<'a> ParserState<'a> { if self.consume(b"$Q") { return Ok(Type::RValueRef(Box::new(self.read_pointee()?), sc)); } - if self.consume(b"$V") { + if self.consume(b"S") || self.consume(b"$V") || self.consume(b"$Z") || self.consume(b"$$V") { return Ok(Type::EmptyParameterPack); } if self.consume(b"$T") { @@ -1182,6 +1182,7 @@ impl<'a> ParserState<'a> { b'J' => Type::Int64(sc), b'K' => Type::Uint64(sc), b'W' => Type::Wchar(sc), + b'Q' => Type::Char(sc), b'S' => Type::Char16(sc), b'U' => Type::Char32(sc), _ => { @@ -1722,15 +1723,13 @@ impl<'a> Serializer<'a> { // Write a function or template parameter list. fn write_types(&mut self, types: &[Type]) -> SerializeResult<()> { - for param in types.iter().take(types.len() - 1) { - self.write_pre(param)?; - self.write_post(param)?; - write!(self.w, ",")?; - if self.flags.contains(DemangleFlags::SPACE_AFTER_COMMA) { - write!(self.w, " ")?; + for (idx, param) in types.iter().filter(|x| **x != Type::EmptyParameterPack).enumerate() { + if idx > 0 { + write!(self.w, ",")?; + if self.flags.contains(DemangleFlags::SPACE_AFTER_COMMA) { + write!(self.w, " ")?; + } } - } - if let Some(param) = types.last() { self.write_pre(param)?; self.write_post(param)?; } @@ -1957,15 +1956,9 @@ impl<'a> Serializer<'a> { } fn write_tmpl_params<'b>(&mut self, params: &Params<'b>) -> SerializeResult<()> { - let types = if let Some(&Type::EmptyParameterPack) = params.types.last() { - ¶ms.types[0..params.types.len() - 1] - } else { - ¶ms.types - }; - write!(self.w, "<")?; - if !types.is_empty() { - self.write_types(types)?; + if !params.types.is_empty() { + self.write_types(¶ms.types)?; if let Some(&b'>') = self.w.last() { write!(self.w, " ")?; } @@ -2818,5 +2811,33 @@ mod tests { "??_V@YAXPEAXAEAVklass@@@Z", "void __cdecl operator delete[](void *,class klass &)", ); + expect( + "?DispatchToCallback@?$I@U?$Y@$S@y@x@@$$V@y@x@@QEAAXV?$C@$$A6AXXZ@base@@@Z", + "public: void __cdecl x::y::I >::DispatchToCallback(class base::C)", + ); + expect( + "?DispatchToCallback@?$I@U?$Y@$$Z@y@x@@$$V@y@x@@QEAAXV?$C@$$A6AXXZ@base@@@Z", + "public: void __cdecl x::y::I >::DispatchToCallback(class base::C)", + ); + expect( + "??$func@H$$ZH@@YAHAEBU?$Foo@H@@0@Z", + "int __cdecl func(struct Foo const &,struct Foo const &)", + ); + expect( + "??$func@HH$$Z@@YAHAEBU?$Foo@H@@0@Z", + "int __cdecl func(struct Foo const &,struct Foo const &)", + ); + expect( + "??$templ_fun_with_pack@$S@@YAXXZ", + "void __cdecl templ_fun_with_pack<>(void)", + ); + expect( + "??$templ_fun_with_ty_pack@$$$V@@YAXXZ", + "void __cdecl templ_fun_with_ty_pack<>(void)", + ); + expect( + "??$templ_fun_with_ty_pack@$$V@@YAXXZ", + "void __cdecl templ_fun_with_ty_pack<>(void)", + ); } }