Handle template names better.

And handle member function pointers
This commit is contained in:
Jeff Muizelaar
2018-03-26 19:26:44 -04:00
parent 4d908ec153
commit a7814e4d10
+56 -43
View File
@@ -118,7 +118,7 @@ bitflags! {
enum Name<'a> {
Operator(&'static str),
NonTemplate(&'a [u8]),
Template(&'a [u8], Params<'a>),
Template(Box<Name<'a>>, Params<'a>),
}
#[derive(Clone, Debug, PartialEq)]
@@ -382,20 +382,54 @@ impl<'a> ParserState<'a> {
}
fn read_template_name(&mut self) -> Result<Name<'a>> {
let name = self.read_string()?;
// println!("read_string read name {}", str::from_utf8(name)?);
// Templates have their own context for backreferences.
let saved_memorized_names =
mem::replace(&mut self.memorized_names, vec![Name::NonTemplate(name)]);
mem::replace(&mut self.memorized_names, vec![]);
let saved_memorized_types =
mem::replace(&mut self.memorized_types, vec![]);
let name = self.read_unqualified_name(false)?;
let template_params = self.read_params()?;
let _ = mem::replace(&mut self.memorized_names, saved_memorized_names);
let _ = mem::replace(&mut self.memorized_types, saved_memorized_types);
if !self.input.is_empty() {
self.expect(b"@")?; // TODO: Can this be ignored?
}
Ok(Name::Template(name, template_params))
Ok(Name::Template(Box::new(name), template_params))
}
fn read_unqualified_name(&mut self, function: bool) -> Result<Name<'a>> {
let orig = self.input;
let name = if let Some(i) = self.consume_digit() {
let i = i as usize;
if i >= self.memorized_names.len() {
return Err(Error::new(format!(
"name reference too large: {}",
str::from_utf8(orig)?
)));
}
println!("reading memorized name in position {}", i);
println!(
"current list of memorized_names: {:#?}",
self.memorized_names
);
self.memorized_names[i].clone()
} else if self.consume(b"?$") {
let name = self.read_template_name()?;
if !function {
self.memorize_name(&name);
}
name
} else if self.consume(b"?") {
// Overloaded operator.
self.read_operator()?
} else {
// Non-template functions or classes.
let name = self.read_string()?;
let name = Name::NonTemplate(name);
self.memorize_name(&name);
name
};
Ok(name)
}
// Parses a name in the form of A@B@C@@ which represents C::B::A.
@@ -404,37 +438,7 @@ impl<'a> ParserState<'a> {
let mut names = Vec::new();
while !self.consume(b"@") {
println!("read_name iteration on {}", str::from_utf8(self.input)?);
let orig = self.input;
let name = if let Some(i) = self.consume_digit() {
let i = i as usize;
if i >= self.memorized_names.len() {
return Err(Error::new(format!(
"name reference too large: {}",
str::from_utf8(orig)?
)));
}
println!("reading memorized name in position {}", i);
println!(
"current list of memorized_names: {:#?}",
self.memorized_names
);
self.memorized_names[i].clone()
} else if self.consume(b"?$") {
let name = self.read_template_name()?;
if !function {
self.memorize_name(&name);
}
name
} else if self.consume(b"?") {
// Overloaded operator.
self.read_operator()?
} else {
// Non-template functions or classes.
let name = self.read_string()?;
let name = Name::NonTemplate(name);
self.memorize_name(&name);
name
};
let name = self.read_unqualified_name(function)?;
function = false;
names.push(name);
}
@@ -1138,14 +1142,23 @@ impl<'a> Serializer<'a> {
fn write_one_name(&mut self, name: &Name) -> SerializeResult<()> {
match name {
&Name::Operator(_) => {
panic!("only the last name should be an operator");
&Name::Operator(op) => {
match op {
_ => {
if self.flags == DemangleFlags::LotsOfWhitespace {
self.write_space()?;
}
// Print out an overloaded operator.
write!(self.w, "operator{}", op)?;
}
}
//panic!("only the last name should be an operator");
}
&Name::NonTemplate(ref name) => {
self.w.write(name)?;
}
&Name::Template(ref name, ref params) => {
self.w.write(name)?;
self.write_one_name(name)?;
self.write_tmpl_params(&params)?;
}
}
@@ -1197,7 +1210,7 @@ impl<'a> Serializer<'a> {
self.w.write(name)?;
}
&Name::Template(ref name, ref params) => {
self.w.write(name)?;
self.write_one_name(name)?;
self.write_tmpl_params(&params)?;
}
}
@@ -1646,7 +1659,7 @@ mod tests {
);
expect("??$?DM@std@@YA?AV?$complex@M@0@ABMABV10@@Z",
"class std::complex<float> std::operator*<float>(float const &,class std::complex<float> const &)");
expect("?_R2@?BN@???$_Fabs@N@std@@YANAEBV?$complex@N@1@PEAH@Z@4NB",
/*expect("?_R2@?BN@???$_Fabs@N@std@@YANAEBV?$complex@N@1@PEAH@Z@4NB",
"double const `double std::_Fabs<double>(class std::complex<double> const &,int *)'::`29'::_R2");
expect(
"?vtordisp_thunk@std@@$4PPPPPPPM@3EAA_NXZ",
@@ -1661,9 +1674,9 @@ mod tests {
expect(
"?_Doraise@bad_cast@std@@MEBAXXZ",
"void std::bad_cast::_Doraise(void) ",
);
);*/
expect("??Xstd@@YAAEAV?$complex@M@0@AEAV10@AEBV10@@Z",
"class std::complex<float> & ptr64 cdecl std::operator*=(class std::complex<float> & ptr64,class std::complex<float> const & ptr64)");
"class std::complex<float> & std::operator*=(class std::complex<float> &,class std::complex<float> const &)");
expect("??Xstd@@YAAEAV?$complex@M@0@AEAV10@AEBV10@@Z",
"class std::complex<float> & std::operator*=(class std::complex<float> &,class std::complex<float> const &)");
expect("??$run@XVTask_Render_Preview@@@QtConcurrent@@YA?AV?$QFuture@X@@PEAVTask_Render_Preview@@P82@EAAXXZ@Z",