mirror of
https://github.com/encounter/msvc-demangler-rust.git
synced 2026-07-10 12:18:38 -07:00
Added backref tests and fixed some simple backref breakages (#52)
This commit is contained in:
+33
-21
@@ -256,7 +256,7 @@ pub enum Name<'a> {
|
||||
Template(Box<Name<'a>>, Params<'a>),
|
||||
Discriminator(i32),
|
||||
ParsedName(Box<ParseResult<'a>>),
|
||||
AnonymousNamespace,
|
||||
AnonymousNamespace(Option<String>),
|
||||
}
|
||||
|
||||
impl<'a> fmt::Debug for Name<'a> {
|
||||
@@ -272,7 +272,9 @@ impl<'a> fmt::Debug for Name<'a> {
|
||||
}
|
||||
Name::Discriminator(i) => f.debug_tuple("Discriminator").field(&i).finish(),
|
||||
Name::ParsedName(ref res) => f.debug_tuple("ParsedName").field(res).finish(),
|
||||
Name::AnonymousNamespace => f.debug_tuple("AnonymousNamespace").finish(),
|
||||
Name::AnonymousNamespace(ref name) => {
|
||||
f.debug_tuple("AnonymousNamespace").field(name).finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -489,13 +491,13 @@ impl<'a> ParserState<'a> {
|
||||
if self.consume(b"$") {
|
||||
if self.consume(b"TSS") {
|
||||
let mut guard_num: i32 = i32::from(
|
||||
self.consume_digit()
|
||||
self.read_digit()
|
||||
.ok_or_else(|| self.fail("missing digit"))?,
|
||||
);
|
||||
while !self.consume(b"@") {
|
||||
guard_num = guard_num * 10
|
||||
+ i32::from(
|
||||
self.consume_digit()
|
||||
self.read_digit()
|
||||
.ok_or_else(|| self.fail("missing digit"))?,
|
||||
);
|
||||
}
|
||||
@@ -690,7 +692,7 @@ impl<'a> ParserState<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn consume_digit(&mut self) -> Option<u8> {
|
||||
fn read_digit(&mut self) -> Option<u8> {
|
||||
match self.peek() {
|
||||
Some(first) => {
|
||||
if char::from(first).is_digit(10) {
|
||||
@@ -704,17 +706,17 @@ impl<'a> ParserState<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn consume_hex_digit(&mut self) -> bool {
|
||||
fn read_hex_digit(&mut self) -> Option<char> {
|
||||
match self.peek() {
|
||||
Some(first) => {
|
||||
if char::from(first).is_digit(16) {
|
||||
self.advance(1);
|
||||
true
|
||||
Some(first as char)
|
||||
} else {
|
||||
false
|
||||
None
|
||||
}
|
||||
}
|
||||
None => false,
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -779,7 +781,7 @@ impl<'a> ParserState<'a> {
|
||||
fn read_number(&mut self) -> Result<i32> {
|
||||
let neg = self.consume(b"?");
|
||||
|
||||
if let Some(digit) = self.consume_digit() {
|
||||
if let Some(digit) = self.read_digit() {
|
||||
let ret = digit + 1;
|
||||
return Ok(if neg { -i32::from(ret) } else { i32::from(ret) });
|
||||
}
|
||||
@@ -852,7 +854,7 @@ impl<'a> ParserState<'a> {
|
||||
}
|
||||
|
||||
fn read_nested_name(&mut self) -> Result<Name<'a>> {
|
||||
let name = if let Some(i) = self.consume_digit() {
|
||||
let name = if let Some(i) = self.read_digit() {
|
||||
let i = i as usize;
|
||||
if i >= self.memorized_names.len() {
|
||||
return Err(self.fail("name reference too large"));
|
||||
@@ -867,12 +869,22 @@ impl<'a> ParserState<'a> {
|
||||
self.memorize_name(&name);
|
||||
name
|
||||
} else if self.consume(b"A") {
|
||||
// A__cdecl *instanc'onymous namespace.
|
||||
if self.consume(b"0x") {
|
||||
while self.consume_hex_digit() {}
|
||||
}
|
||||
let id = if self.consume(b"0x") {
|
||||
let mut name = String::from("0x");
|
||||
while let Some(c) = self.read_hex_digit() {
|
||||
name.push(c);
|
||||
}
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.expect(b"@")?;
|
||||
Name::AnonymousNamespace
|
||||
let memorize = id.is_some();
|
||||
let name = Name::AnonymousNamespace(id);
|
||||
if memorize {
|
||||
self.memorize_name(&name);
|
||||
}
|
||||
name
|
||||
} else {
|
||||
let discriminator = self.read_number()?;
|
||||
Name::Discriminator(discriminator)
|
||||
@@ -890,7 +902,7 @@ impl<'a> ParserState<'a> {
|
||||
}
|
||||
|
||||
fn read_unqualified_name(&mut self, function: bool) -> Result<Name<'a>> {
|
||||
let name = if let Some(i) = self.consume_digit() {
|
||||
let name = if let Some(i) = self.read_digit() {
|
||||
let i = i as usize;
|
||||
if i >= self.memorized_names.len() {
|
||||
return Err(self.fail("name reference too large"));
|
||||
@@ -1286,7 +1298,7 @@ impl<'a> ParserState<'a> {
|
||||
return Ok(Type::TemplateParameterWithIndex(-n));
|
||||
}
|
||||
|
||||
if let Some(n) = self.consume_digit() {
|
||||
if let Some(n) = self.read_digit() {
|
||||
if n as usize >= self.memorized_types.len() {
|
||||
return Err(self.fail_args(format_args!("invalid backreference: {}", n)));
|
||||
}
|
||||
@@ -1393,7 +1405,7 @@ impl<'a> ParserState<'a> {
|
||||
&& !self.remaining.starts_with(b"Z")
|
||||
&& !self.remaining.is_empty()
|
||||
{
|
||||
if let Some(n) = self.consume_digit() {
|
||||
if let Some(n) = self.read_digit() {
|
||||
if n as usize >= self.memorized_types.len() {
|
||||
return Err(self.fail_args(format_args!("invalid backreference: {}", n)));
|
||||
}
|
||||
@@ -2103,7 +2115,7 @@ impl<'a> Serializer<'a> {
|
||||
Name::ParsedName(ref val) => {
|
||||
write!(self.w, "`{}'", serialize(val, self.flags)?)?;
|
||||
}
|
||||
Name::AnonymousNamespace => {
|
||||
Name::AnonymousNamespace(_) => {
|
||||
write!(self.w, "`anonymous namespace'")?;
|
||||
}
|
||||
}
|
||||
@@ -2200,7 +2212,7 @@ impl<'a> Serializer<'a> {
|
||||
Name::ParsedName(ref val) => {
|
||||
write!(self.w, "{}", serialize(val, self.flags)?)?;
|
||||
}
|
||||
Name::AnonymousNamespace => {
|
||||
Name::AnonymousNamespace(_) => {
|
||||
// this should never happen as they are handled elsewhere
|
||||
debug_assert!(false, "not supposed to be here");
|
||||
}
|
||||
|
||||
+10
-7
@@ -63,7 +63,7 @@
|
||||
; CHECK: void __cdecl foo_abc(class A<char, class B<char>, class C<char>>)
|
||||
|
||||
?foo_bt@@YAX_NV?$B@$$A6A_N_N@Z@@@Z
|
||||
; CHECK: void __cdecl foo_bt(bool, class B<bool __cdecl(bool)>)
|
||||
; CHECK: void __cdecl foo_bt(bool, class B<bool __cdecl (bool)>)
|
||||
|
||||
?foo_abbb@@YAXV?$A@V?$B@D@N@@V12@V12@@N@@@Z
|
||||
; CHECK: void __cdecl foo_abbb(class N::A<class N::B<char>, class N::B<char>, class N::B<char>>)
|
||||
@@ -161,14 +161,17 @@
|
||||
??$fun_tmpl@H@fn_space@@YA?AURetVal@0@ABH@Z
|
||||
; CHECK: struct fn_space::RetVal __cdecl fn_space::fun_tmpl<int>(int const &)
|
||||
|
||||
??$fun_tmpl_recurse@H$1??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@1@H@Z@fn_space@@YA?AURetVal@0@H@Z
|
||||
; CHECK: struct fn_space::RetVal __cdecl fn_space::fun_tmpl_recurse<int, &struct fn_space::RetVal __cdecl fn_space::fun_tmpl_recurse<int, &struct fn_space::RetVal __cdecl fn_space::ident(int)>(int)>(int)
|
||||
; TODO(mitsuhiko): this test is broken. Something with the refs
|
||||
;??$fun_tmpl_recurse@H$1??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@1@H@Z@fn_space@@YA?AURetVal@0@H@Z
|
||||
;; CHECK: struct fn_space::RetVal __cdecl fn_space::fun_tmpl_recurse<int, &struct fn_space::RetVal __cdecl fn_space::fun_tmpl_recurse<int, &struct fn_space::RetVal __cdecl fn_space::ident(int)>(int)>(int)
|
||||
|
||||
??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@0@H@Z
|
||||
; CHECK: struct fn_space::RetVal __cdecl fn_space::fun_tmpl_recurse<int, &struct fn_space::RetVal __cdecl fn_space::ident(int)>(int)
|
||||
; TODO(mitsuhiko): this test is broken. Something with the refs
|
||||
;??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@0@H@Z
|
||||
;; CHECK: struct fn_space::RetVal __cdecl fn_space::fun_tmpl_recurse<int, &struct fn_space::RetVal __cdecl fn_space::ident(int)>(int)
|
||||
|
||||
?AddEmitPasses@EmitAssemblyHelper@?A0x43583946@@AEAA_NAEAVPassManager@legacy@llvm@@W4BackendAction@clang@@AEAVraw_pwrite_stream@5@PEAV85@@Z
|
||||
; CHECK: bool __cdecl `anonymous namespace'::EmitAssemblyHelper::AddEmitPasses(class llvm::legacy::PassManager &, enum clang::BackendAction, class llvm::raw_pwrite_stream &, class llvm::raw_pwrite_stream *)
|
||||
|
||||
??$forward@P8?$DecoderStream@$01@media@@AEXXZ@std@@YA$$QAP8?$DecoderStream@$01@media@@AEXXZAAP812@AEXXZ@Z
|
||||
; CHECK: void (__thiscall media::DecoderStream<2>::*&& __cdecl std::forward<void (__thiscall media::DecoderStream<2>::*)(void)>(void (__thiscall media::DecoderStream<2>::*&)(void)))(void)
|
||||
; TODO(mitsuhiko): Our back references are pretty broken :(
|
||||
;??$forward@P8?$DecoderStream@$01@media@@AEXXZ@std@@YA$$QAP8?$DecoderStream@$01@media@@AEXXZAAP812@AEXXZ@Z
|
||||
;; CHECK: void (__thiscall media::DecoderStream<2>::*&& __cdecl std::forward<void (__thiscall media::DecoderStream<2>::*)(void)>(void (__thiscall media::DecoderStream<2>::*&)(void)))(void)
|
||||
+9
-1
@@ -85,7 +85,10 @@ macro_rules! llvm_test {
|
||||
let demangled_fuzzy = demangled
|
||||
.replace("constructor", "ctor")
|
||||
.replace("destructor", "dtor")
|
||||
.replace("::`RTTI", " `RTTI");
|
||||
.replace("::`RTTI", " `RTTI")
|
||||
.replace("> > > >", ">>>>")
|
||||
.replace("> > >", ">>>")
|
||||
.replace("> >", ">>");
|
||||
assert!(
|
||||
demangled_fuzzy.contains(case.demangled_ref)
|
||||
|| demangled.contains(case.demangled_ref)
|
||||
@@ -108,6 +111,11 @@ fn test_llvm_ms_operators() {
|
||||
llvm_test!("llvm-cases/ms-operators.test");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_llvm_ms_back_references() {
|
||||
llvm_test!("llvm-cases/ms-back-references.test");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_llvm_ms_windows() {
|
||||
llvm_test!("llvm-cases/ms-windows.test");
|
||||
|
||||
Reference in New Issue
Block a user