1 //! Abstract syntax tree types for mangled symbols.
2
3 use super::{DemangleWrite, DemangleNodeType, DemangleOptions};
4 use error::{self, Result};
5 use index_str::IndexStr;
6 use std::cell::Cell;
7 #[cfg(feature = "logging")]
8 use std::cell::RefCell;
9 use std::fmt::{self, Write};
10 use std::hash::{Hash, Hasher};
11 use std::mem;
12 use std::ops;
13 use std::ptr;
14 use subs::{Substitutable, SubstitutionTable};
15 use string::String;
16 use vec::Vec;
17 use boxed::Box;
18
19 struct AutoLogParse;
20
21 #[cfg(feature = "logging")]
22 thread_local! {
23 static LOG_DEPTH: RefCell<usize> = RefCell::new(0);
24 }
25
26 impl AutoLogParse {
27 #[cfg(feature = "logging")]
new(production: &'static str, input: IndexStr<'_>) -> AutoLogParse28 fn new(production: &'static str, input: IndexStr<'_>) -> AutoLogParse {
29 LOG_DEPTH.with(|depth| {
30 if *depth.borrow() == 0 {
31 println!();
32 }
33
34 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
35 log!(
36 "{}({} \"{}\"",
37 indent,
38 production,
39 String::from_utf8_lossy(input.as_ref())
40 );
41 *depth.borrow_mut() += 1;
42 });
43 AutoLogParse
44 }
45
46 #[cfg(not(feature = "logging"))]
47 #[inline(always)]
new(_: &'static str, _: IndexStr) -> AutoLogParse48 fn new(_: &'static str, _: IndexStr) -> AutoLogParse {
49 AutoLogParse
50 }
51 }
52
53 #[cfg(feature = "logging")]
54 impl Drop for AutoLogParse {
drop(&mut self)55 fn drop(&mut self) {
56 LOG_DEPTH.with(|depth| {
57 *depth.borrow_mut() -= 1;
58 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
59 log!("{})", indent);
60 });
61 }
62 }
63
64 /// Performs the two operations that begin every parse:
65 ///
66 /// 1. Keeps track of recursion levels and early returns with an error if there
67 /// is too much recursion.
68 ///
69 /// 2. Automatically log start and end parsing in an s-expression format, when the
70 /// `logging` feature is enabled.
71 macro_rules! try_begin_parse {
72 ( $production:expr , $ctx:expr , $input:expr ) => {
73 let _log = AutoLogParse::new($production, $input);
74 let _auto_check_recursion = AutoParseRecursion::new($ctx)?;
75 }
76 }
77
78 struct AutoLogDemangle;
79
80 impl AutoLogDemangle {
81 #[cfg(feature = "logging")]
new<P, W>( production: &P, ctx: &DemangleContext<W>, scope: Option<ArgScopeStack>, is_inner: bool, ) -> AutoLogDemangle where P: ?Sized + fmt::Debug, W: DemangleWrite,82 fn new<P, W>(
83 production: &P,
84 ctx: &DemangleContext<W>,
85 scope: Option<ArgScopeStack>,
86 is_inner: bool,
87 ) -> AutoLogDemangle
88 where
89 P: ?Sized + fmt::Debug,
90 W: DemangleWrite,
91 {
92 LOG_DEPTH.with(|depth| {
93 if *depth.borrow() == 0 {
94 println!();
95 }
96
97 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
98 log!("{}(", indent);
99 log!(
100 "{} {}{:?}",
101 indent,
102 if is_inner { "as_inner: " } else { "" },
103 production
104 );
105 log!("{} inner = {:?}", indent, ctx.inner);
106 log!("{} scope = {:?}", indent, scope);
107
108 *depth.borrow_mut() += 1;
109 });
110 AutoLogDemangle
111 }
112
113 #[cfg(not(feature = "logging"))]
114 #[inline(always)]
new<P, W>( _: &P, _: &DemangleContext<W>, _: Option<ArgScopeStack>, _: bool, ) -> AutoLogDemangle where P: ?Sized + fmt::Debug, W: DemangleWrite,115 fn new<P, W>(
116 _: &P,
117 _: &DemangleContext<W>,
118 _: Option<ArgScopeStack>,
119 _: bool,
120 ) -> AutoLogDemangle
121 where
122 P: ?Sized + fmt::Debug,
123 W: DemangleWrite,
124 {
125 AutoLogDemangle
126 }
127 }
128
129 #[cfg(feature = "logging")]
130 impl Drop for AutoLogDemangle {
drop(&mut self)131 fn drop(&mut self) {
132 LOG_DEPTH.with(|depth| {
133 *depth.borrow_mut() -= 1;
134 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
135 log!("{})", indent);
136 });
137 }
138 }
139
140 /// Automatically log start and end demangling in an s-expression format, when
141 /// the `logging` feature is enabled.
142 macro_rules! try_begin_demangle {
143 ( $production:expr, $ctx:expr, $scope:expr ) => {{
144 let _log = AutoLogDemangle::new($production, $ctx, $scope, false);
145 &mut AutoParseDemangle::new($ctx)?
146 }}
147 }
148
149 /// Automatically log start and end demangling in an s-expression format, when
150 /// the `logging` feature is enabled.
151 macro_rules! try_begin_demangle_as_inner {
152 ( $production:expr, $ctx:expr, $scope:expr ) => {{
153 let _log = AutoLogDemangle::new($production, $ctx, $scope, true);
154 &mut AutoParseDemangle::new($ctx)?
155 }}
156 }
157
158 #[derive(Debug, Default, Clone, Copy)]
159 struct ParseContextState {
160 // The current recursion level. Should always be less than or equal to the
161 // maximum.
162 recursion_level: u32,
163 // Whether or not we are currently parsing a conversion operator.
164 in_conversion: bool,
165 }
166
167 /// Common context needed when parsing.
168 #[derive(Debug, Clone)]
169 pub struct ParseContext {
170 // Maximum amount of recursive parsing calls we will allow. If this is too
171 // large, we can blow the stack.
172 max_recursion: u32,
173 // Mutable state within the `ParseContext`.
174 state: Cell<ParseContextState>,
175 }
176
177 impl Default for ParseContext {
default() -> ParseContext178 fn default() -> ParseContext {
179 ParseContext {
180 max_recursion: 64,
181 state: Cell::new(ParseContextState::default()),
182 }
183 }
184 }
185
186 impl ParseContext {
187 /// Get the current recursion level for this context.
recursion_level(&self) -> u32188 pub fn recursion_level(&self) -> u32 {
189 self.state.get().recursion_level
190 }
191
192 #[inline]
enter_recursion(&self) -> error::Result<()>193 fn enter_recursion(&self) -> error::Result<()> {
194 let mut state = self.state.get();
195 let new_recursion_level = state.recursion_level + 1;
196
197 if new_recursion_level >= self.max_recursion {
198 log!("Hit too much recursion at level {}", self.max_recursion);
199 Err(error::Error::TooMuchRecursion)
200 } else {
201 state.recursion_level = new_recursion_level;
202 self.state.set(state);
203 Ok(())
204 }
205 }
206
207 #[inline]
exit_recursion(&self)208 fn exit_recursion(&self) {
209 let mut state = self.state.get();
210 debug_assert!(state.recursion_level >= 1);
211 state.recursion_level -= 1;
212 self.state.set(state);
213 }
214
215 #[inline]
in_conversion(&self) -> bool216 fn in_conversion(&self) -> bool {
217 self.state.get().in_conversion
218 }
219
set_in_conversion(&self, in_conversion: bool) -> bool220 fn set_in_conversion(&self, in_conversion: bool) -> bool {
221 let mut state = self.state.get();
222 let previously_in_conversion = state.in_conversion;
223 state.in_conversion = in_conversion;
224 self.state.set(state);
225 previously_in_conversion
226 }
227 }
228
229 /// An RAII type to automatically check the recursion level against the
230 /// maximum. If the maximum has been crossed, return an error. Otherwise,
231 /// increment the level upon construction, and decrement it upon destruction.
232 struct AutoParseRecursion<'a>(&'a ParseContext);
233
234 impl<'a> AutoParseRecursion<'a> {
235 #[inline]
new(ctx: &'a ParseContext) -> error::Result<AutoParseRecursion<'a>>236 fn new(ctx: &'a ParseContext) -> error::Result<AutoParseRecursion<'a>> {
237 ctx.enter_recursion()?;
238 Ok(AutoParseRecursion(ctx))
239 }
240 }
241
242 impl<'a> Drop for AutoParseRecursion<'a> {
243 #[inline]
drop(&mut self)244 fn drop(&mut self) {
245 self.0.exit_recursion();
246 }
247 }
248
249 /// A trait for anything that can be parsed from an `IndexStr` and return a
250 /// `Result` of the parsed `Self` value and the rest of the `IndexStr` input
251 /// that has not been consumed in parsing the `Self` value.
252 ///
253 /// For AST types representing productions which have `<substitution>` as a
254 /// possible right hand side, do not implement this trait directly. Instead,
255 /// make a newtype over `usize`, parse either the `<substitution>` back
256 /// reference or "real" value, insert the "real" value into the substitution
257 /// table if needed, and *always* return the newtype index into the substitution
258 /// table.
259 #[doc(hidden)]
260 pub trait Parse: Sized {
261 /// Parse the `Self` value from `input` and return it, updating the
262 /// substitution table as needed.
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Self, IndexStr<'b>)>263 fn parse<'a, 'b>(
264 ctx: &'a ParseContext,
265 subs: &'a mut SubstitutionTable,
266 input: IndexStr<'b>,
267 ) -> Result<(Self, IndexStr<'b>)>;
268 }
269
270 /// Determine whether this AST node is an instantiated[*] template function, and
271 /// get its concrete template arguments.
272 ///
273 /// [*] Note that we will never see an abstract, un-instantiated template
274 /// function, since they don't end up in object files and don't get mangled
275 /// names.
276 trait GetTemplateArgs {
277 /// Returns `Some` if this is a template function, `None` otherwise.
get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>278 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>;
279 }
280
281 /// A leaf name is the part the name that describes some type or class without
282 /// any leading namespace qualifiers.
283 ///
284 /// This is used when figuring out how to format constructors and destructors,
285 /// which are formatted as `gooble::dodo::Thing::~Thing()` but we don't have
286 /// direct access to `Thing` in the `CtorDtorName` AST.
287 #[derive(Debug)]
288 pub(crate) enum LeafName<'a> {
289 SourceName(&'a SourceName),
290 WellKnownComponent(&'a WellKnownComponent),
291 Closure(&'a ClosureTypeName),
292 UnnamedType(&'a UnnamedTypeName),
293 }
294
295 impl<'subs, W> DemangleAsLeaf<'subs, W> for LeafName<'subs>
296 where
297 W: 'subs + DemangleWrite,
298 {
demangle_as_leaf<'me, 'ctx>( &'me self, ctx: &'ctx mut DemangleContext<'subs, W>, ) -> fmt::Result299 fn demangle_as_leaf<'me, 'ctx>(
300 &'me self,
301 ctx: &'ctx mut DemangleContext<'subs, W>,
302 ) -> fmt::Result {
303 match *self {
304 LeafName::SourceName(sn) => sn.demangle(ctx, None),
305 LeafName::Closure(c) => c.demangle(ctx, None),
306 LeafName::WellKnownComponent(wkc) => wkc.demangle_as_leaf(ctx),
307 LeafName::UnnamedType(utn) => utn.demangle_as_leaf(ctx),
308 }
309 }
310 }
311
312 /// Determine whether this AST node is some kind (potentially namespaced) name
313 /// and if so get its leaf name.
314 pub(crate) trait GetLeafName<'a> {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>315 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>;
316 }
317
318 /// Determine whether this AST node is a constructor, destructor, or conversion
319 /// function.
320 pub(crate) trait IsCtorDtorConversion {
is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool321 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool;
322 }
323
324 /// When formatting a mangled symbol's parsed AST as a demangled symbol, we need
325 /// to resolve indirect references to template and function arguments with
326 /// direct `TemplateArg` and `Type` references respectively.
327 ///
328 /// Note that which set of arguments are implicitly referenced change as we
329 /// enter and leave different functions' scope. One might usually use de Brujin
330 /// indices to keep arguments within scopes separated from each other, but the
331 /// Itanium C++ ABI does not allow us the luxury. AFAIK, when the ABI was first
332 /// drafted, C++ did not have lambdas, and the issue did not come up at all
333 /// since a function simply couldn't refer to the types of closed over
334 /// variables.
335 ///
336 /// This trait is implemented by anything that can potentially resolve arguments
337 /// for us.
338 trait ArgScope<'me, 'ctx>: fmt::Debug {
339 /// Get the current scope's leaf name.
leaf_name(&'me self) -> Result<LeafName<'ctx>>340 fn leaf_name(&'me self) -> Result<LeafName<'ctx>>;
341
342 /// Get the current scope's `index`th template argument.
get_template_arg(&'me self, index: usize) -> Result<(&'ctx TemplateArg, &'ctx TemplateArgs)>343 fn get_template_arg(&'me self, index: usize) -> Result<(&'ctx TemplateArg, &'ctx TemplateArgs)>;
344
345 /// Get the current scope's `index`th function argument's type.
get_function_arg(&'me self, index: usize) -> Result<&'ctx Type>346 fn get_function_arg(&'me self, index: usize) -> Result<&'ctx Type>;
347 }
348
349 /// An `ArgScopeStack` represents the current function and template demangling
350 /// scope we are within. As we enter new demangling scopes, we construct new
351 /// `ArgScopeStack`s whose `prev` references point back to the old ones. These
352 /// `ArgScopeStack`s are kept on the native stack, and as functions return, they
353 /// go out of scope and we use the previous `ArgScopeStack`s again.
354 #[derive(Copy, Clone, Debug)]
355 pub struct ArgScopeStack<'prev, 'subs>
356 where
357 'subs: 'prev,
358 {
359 item: &'subs dyn ArgScope<'subs, 'subs>,
360 in_arg: Option<(usize, &'subs TemplateArgs)>,
361 prev: Option<&'prev ArgScopeStack<'prev, 'subs>>,
362 }
363
364 /// When we first begin demangling, we haven't entered any function or template
365 /// demangling scope and we don't have any useful `ArgScopeStack`. Therefore, we
366 /// are never actually dealing with `ArgScopeStack` directly in practice, but
367 /// always an `Option<ArgScopeStack>` instead. Nevertheless, we want to define
368 /// useful methods on `Option<ArgScopeStack>`.
369 ///
370 /// A custom "extension" trait with exactly one implementor: Rust's principled
371 /// monkey patching!
372 trait ArgScopeStackExt<'prev, 'subs>: Copy {
373 /// Push a new `ArgScope` onto this `ArgScopeStack` and return the new
374 /// `ArgScopeStack` with the pushed resolver on top.
push( &'prev self, item: &'subs dyn ArgScope<'subs, 'subs>, ) -> Option<ArgScopeStack<'prev, 'subs>>375 fn push(
376 &'prev self,
377 item: &'subs dyn ArgScope<'subs, 'subs>,
378 ) -> Option<ArgScopeStack<'prev, 'subs>>;
379 }
380
381 impl<'prev, 'subs> ArgScopeStackExt<'prev, 'subs> for Option<ArgScopeStack<'prev, 'subs>> {
push( &'prev self, item: &'subs dyn ArgScope<'subs, 'subs>, ) -> Option<ArgScopeStack<'prev, 'subs>>382 fn push(
383 &'prev self,
384 item: &'subs dyn ArgScope<'subs, 'subs>,
385 ) -> Option<ArgScopeStack<'prev, 'subs>> {
386 log!("ArgScopeStack::push: {:?}", item);
387 Some(ArgScopeStack {
388 prev: self.as_ref(),
389 in_arg: None,
390 item: item,
391 })
392 }
393 }
394
395 /// A stack of `ArgScope`s is itself an `ArgScope`!
396 impl<'prev, 'subs> ArgScope<'prev, 'subs> for Option<ArgScopeStack<'prev, 'subs>> {
leaf_name(&'prev self) -> Result<LeafName<'subs>>397 fn leaf_name(&'prev self) -> Result<LeafName<'subs>> {
398 let mut scope = self.as_ref();
399 while let Some(s) = scope {
400 if let Ok(c) = s.item.leaf_name() {
401 return Ok(c);
402 }
403 scope = s.prev;
404 }
405 Err(error::Error::BadLeafNameReference)
406 }
407
get_template_arg(&'prev self, idx: usize) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)>408 fn get_template_arg(&'prev self, idx: usize) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
409 let mut scope = self.as_ref();
410 while let Some(s) = scope {
411 if let Ok((arg, args)) = s.item.get_template_arg(idx) {
412 if let Some((in_idx, in_args)) = s.in_arg {
413 if args as *const TemplateArgs == in_args as *const TemplateArgs &&
414 in_idx <= idx {
415 return Err(error::Error::ForwardTemplateArgReference);
416 }
417 }
418 return Ok((arg, args));
419 }
420 scope = s.prev;
421 }
422
423 Err(error::Error::BadTemplateArgReference)
424 }
425
get_function_arg(&'prev self, idx: usize) -> Result<&'subs Type>426 fn get_function_arg(&'prev self, idx: usize) -> Result<&'subs Type> {
427 let mut scope = self.as_ref();
428 while let Some(s) = scope {
429 if let Ok(arg) = s.item.get_function_arg(idx) {
430 return Ok(arg);
431 }
432 scope = s.prev;
433 }
434
435 Err(error::Error::BadFunctionArgReference)
436 }
437 }
438
439 #[derive(Debug, Copy, Clone)]
440 struct DemangleState {
441 /// How deep in the demangling are we?
442 pub recursion_level: u32,
443 }
444
445 /// An RAII type to automatically check the recursion level against the
446 /// maximum. If the maximum has been crossed, return an error. Otherwise,
447 /// increment the level upon construction, and decrement it upon destruction.
448 struct AutoParseDemangle<'a, 'b, W: 'a + DemangleWrite>(&'b mut DemangleContext<'a, W>);
449
450 impl<'a, 'b, W: 'a + DemangleWrite> AutoParseDemangle<'a, 'b, W> {
451 #[inline]
new(ctx: &'b mut DemangleContext<'a, W>) -> std::result::Result<Self, fmt::Error>452 fn new(ctx: &'b mut DemangleContext<'a, W>) -> std::result::Result<Self, fmt::Error> {
453 ctx.enter_recursion()?;
454 Ok(AutoParseDemangle(ctx))
455 }
456 }
457
458 impl<'a, 'b, W: 'a + DemangleWrite> std::ops::Deref for AutoParseDemangle<'a, 'b, W> {
459 type Target = DemangleContext<'a, W>;
460
deref(&self) -> &Self::Target461 fn deref(&self) -> &Self::Target {
462 self.0
463 }
464 }
465
466 impl<'a, 'b, W: 'a + DemangleWrite> std::ops::DerefMut for AutoParseDemangle<'a, 'b, W> {
deref_mut(&mut self) -> &mut Self::Target467 fn deref_mut(&mut self) -> &mut Self::Target {
468 self.0
469 }
470 }
471
472 impl<'a, 'b, W: 'a + DemangleWrite> Drop for AutoParseDemangle<'a, 'b, W> {
473 #[inline]
drop(&mut self)474 fn drop(&mut self) {
475 self.0.exit_recursion();
476 }
477 }
478
479 /// Common state that is required when demangling a mangled symbol's parsed AST.
480 #[doc(hidden)]
481 #[derive(Debug)]
482 pub struct DemangleContext<'a, W>
483 where
484 W: 'a + DemangleWrite,
485 {
486 // The substitution table built up when parsing the mangled symbol into an
487 // AST.
488 subs: &'a SubstitutionTable,
489
490 // The maximum recursion
491 max_recursion: u32,
492
493 // Sometimes an AST node needs to insert itself as an inner item within one
494 // of its children when demangling that child. For example, the AST
495 //
496 // (array 10 int)
497 //
498 // is demangled as `int[10]`, but if we were to demangle the AST
499 //
500 // (lvalue-ref (array 10 int))
501 //
502 // then we would want this demangled form: `int (&) [10]`, which requires
503 // the parent lvalue-ref to be passed into the child array's demangling
504 // method. This kind of thing also pops up with function pointers.
505 //
506 // The `inner` stack enables such behavior by allowing us to pass AST
507 // parents down to their children as inner items.
508 inner: Vec<&'a dyn DemangleAsInner<'a, W>>,
509
510 // The original input string.
511 input: &'a [u8],
512
513 // `Identifier`s will be placed here, so `UnnamedTypeName` can utilize and print
514 // out the Constructor/Destructor used.
515 source_name: Option<&'a str>,
516
517 // What the demangled name is being written to.
518 out: &'a mut W,
519
520 // The total number of bytes written to `out`. This is maintained by the
521 // `Write` implementation for `DemangleContext`.
522 bytes_written: usize,
523
524 // The last char written to `out`, if any.
525 last_char_written: Option<char>,
526
527 // We are currently demangling a lambda argument, so template substitution
528 // should be suppressed to match libiberty.
529 is_lambda_arg: bool,
530
531 // We are currently demangling a template-prefix.
532 is_template_prefix: bool,
533
534 // We are currently demangling a template-prefix in a nested-name.
535 is_template_prefix_in_nested_name: bool,
536
537 // `PackExpansion`'s should only print '...', only when there is no template
538 // argument pack.
539 is_template_argument_pack: bool,
540
541 // Whether to show function parameters.
542 // This must be set to true before calling `demangle` on `Encoding`
543 // unless that call is via the toplevel call to `MangledName::demangle`.
544 show_params: bool,
545
546 // Whether to show function return types.
547 // This must be set to true before calling `demangle` on `Encoding`
548 // unless that call is via the toplevel call to `MangledName::demangle`.
549 show_return_type: bool,
550
551 // recursion protection.
552 state: Cell<DemangleState>,
553 }
554
555 impl<'a, W> fmt::Write for DemangleContext<'a, W>
556 where
557 W: 'a + DemangleWrite,
558 {
write_str(&mut self, s: &str) -> fmt::Result559 fn write_str(&mut self, s: &str) -> fmt::Result {
560 if s.is_empty() {
561 return Ok(());
562 }
563
564 log!("DemangleContext::write: '{}'", s);
565
566 self.out.write_string(s).map(|_| {
567 self.last_char_written = s.chars().last();
568 self.bytes_written += s.len();
569 })
570 }
571 }
572
573 impl<'a, W> DemangleContext<'a, W>
574 where
575 W: 'a + DemangleWrite,
576 {
577 /// Construct a new `DemangleContext`.
new( subs: &'a SubstitutionTable, input: &'a [u8], options: DemangleOptions, out: &'a mut W, ) -> DemangleContext<'a, W>578 pub fn new(
579 subs: &'a SubstitutionTable,
580 input: &'a [u8],
581 options: DemangleOptions,
582 out: &'a mut W,
583 ) -> DemangleContext<'a, W> {
584 DemangleContext {
585 subs: subs,
586 max_recursion: 128,
587 inner: vec![],
588 input: input,
589 source_name: None,
590 out: out,
591 bytes_written: 0,
592 last_char_written: None,
593 is_lambda_arg: false,
594 is_template_prefix: false,
595 is_template_prefix_in_nested_name: false,
596 is_template_argument_pack: false,
597 show_params: !options.no_params,
598 show_return_type: !options.no_return_type,
599 state: Cell::new(DemangleState {
600 recursion_level: 0,
601 }),
602 }
603 }
604
605 /// Get the current recursion level for this context.
recursion_level(&self) -> u32606 pub fn recursion_level(&self) -> u32 {
607 self.state.get().recursion_level
608 }
609
610 #[inline]
enter_recursion(&self) -> fmt::Result611 fn enter_recursion(&self) -> fmt::Result {
612 let mut state = self.state.get();
613 let new_recursion_level = state.recursion_level + 1;
614
615 if new_recursion_level >= self.max_recursion {
616 log!("Hit too much recursion at level {}", self.max_recursion);
617 Err(Default::default())
618 } else {
619 state.recursion_level = new_recursion_level;
620 self.state.set(state);
621 Ok(())
622 }
623 }
624
625 #[inline]
exit_recursion(&self)626 fn exit_recursion(&self) {
627 let mut state = self.state.get();
628 debug_assert!(state.recursion_level >= 1);
629 state.recursion_level -= 1;
630 self.state.set(state);
631 }
632
633 #[inline]
ensure(&mut self, ch: char) -> fmt::Result634 fn ensure(&mut self, ch: char) -> fmt::Result {
635 if self.last_char_written == Some(ch) {
636 Ok(())
637 } else {
638 write!(self, "{}", ch)?;
639 Ok(())
640 }
641 }
642
643 #[inline]
ensure_space(&mut self) -> fmt::Result644 fn ensure_space(&mut self) -> fmt::Result {
645 self.ensure(' ')
646 }
647
648 #[inline]
push_inner(&mut self, item: &'a dyn DemangleAsInner<'a, W>)649 fn push_inner(&mut self, item: &'a dyn DemangleAsInner<'a, W>) {
650 log!("DemangleContext::push_inner: {:?}", item);
651 self.inner.push(item);
652 }
653
654 #[inline]
pop_inner(&mut self) -> Option<&'a dyn DemangleAsInner<'a, W>>655 fn pop_inner(&mut self) -> Option<&'a dyn DemangleAsInner<'a, W>> {
656 let popped = self.inner.pop();
657 log!("DemangleContext::pop_inner: {:?}", popped);
658 popped
659 }
660
661 #[inline]
pop_inner_if(&mut self, inner: &'a dyn DemangleAsInner<'a, W>) -> bool662 fn pop_inner_if(&mut self, inner: &'a dyn DemangleAsInner<'a, W>) -> bool {
663 let last = match self.inner.last() {
664 None => return false,
665 Some(last) => *last,
666 };
667
668 if ptr::eq(last, inner) {
669 self.inner.pop();
670 true
671 } else {
672 false
673 }
674 }
675
demangle_inner_prefixes<'prev>( &mut self, scope: Option<ArgScopeStack<'prev, 'a>>, ) -> fmt::Result676 fn demangle_inner_prefixes<'prev>(
677 &mut self,
678 scope: Option<ArgScopeStack<'prev, 'a>>,
679 ) -> fmt::Result {
680 log!("DemangleContext::demangle_inner_prefixes");
681 let mut new_inner = vec![];
682 while let Some(inner) = self.pop_inner() {
683 if inner
684 .downcast_to_function_type()
685 .map_or(false, |f| !f.cv_qualifiers.is_empty())
686 {
687 log!(
688 "DemangleContext::demangle_inner_prefixes: not a prefix, saving: {:?}",
689 inner
690 );
691 new_inner.push(inner);
692 } else {
693 log!(
694 "DemangleContext::demangle_inner_prefixes: demangling prefix: {:?}",
695 inner
696 );
697 inner.demangle_as_inner(self, scope)?;
698 }
699 }
700 new_inner.reverse();
701 self.inner = new_inner;
702 Ok(())
703 }
704
demangle_inners<'prev>( &mut self, scope: Option<ArgScopeStack<'prev, 'a>>, ) -> fmt::Result705 fn demangle_inners<'prev>(
706 &mut self,
707 scope: Option<ArgScopeStack<'prev, 'a>>,
708 ) -> fmt::Result {
709 while let Some(inner) = self.pop_inner() {
710 inner.demangle_as_inner(self, scope)?;
711 }
712 Ok(())
713 }
714
set_source_name(&mut self, start: usize, end: usize)715 fn set_source_name(&mut self, start: usize, end: usize) {
716 let ident = &self.input[start..end];
717 self.source_name = std::str::from_utf8(ident).ok();
718 }
719
push_demangle_node(&mut self, t: DemangleNodeType)720 fn push_demangle_node(&mut self, t: DemangleNodeType) {
721 self.out.push_demangle_node(t);
722 }
723
724 /// This should not be called on error paths.
725 /// pop_inner_if already doesn't balance if there are errors.
pop_demangle_node(&mut self)726 fn pop_demangle_node(&mut self) {
727 self.out.pop_demangle_node();
728 }
729 }
730
731 #[doc(hidden)]
732 #[derive(Debug)]
733 pub struct AutoDemangleContextInnerBarrier<'ctx, 'a, W>
734 where
735 W: 'a + DemangleWrite,
736 'a: 'ctx,
737 {
738 ctx: &'ctx mut DemangleContext<'a, W>,
739 saved_inner: Vec<&'a dyn DemangleAsInner<'a, W>>,
740 }
741
742 impl<'ctx, 'a, W> AutoDemangleContextInnerBarrier<'ctx, 'a, W>
743 where
744 W: 'a + DemangleWrite,
745 'a: 'ctx,
746 {
747 /// Set aside the current inner stack on the demangle context.
new(ctx: &'ctx mut DemangleContext<'a, W>) -> Self748 pub fn new(ctx: &'ctx mut DemangleContext<'a, W>) -> Self {
749 let mut saved_inner = vec![];
750 mem::swap(&mut saved_inner, &mut ctx.inner);
751 AutoDemangleContextInnerBarrier {
752 ctx: ctx,
753 saved_inner: saved_inner,
754 }
755 }
756 }
757
758 impl<'ctx, 'a, W> ops::Deref for AutoDemangleContextInnerBarrier<'ctx, 'a, W>
759 where
760 W: 'a + DemangleWrite,
761 'a: 'ctx,
762 {
763 type Target = DemangleContext<'a, W>;
764
deref(&self) -> &Self::Target765 fn deref(&self) -> &Self::Target {
766 self.ctx
767 }
768 }
769
770 impl<'ctx, 'a, W> ops::DerefMut for AutoDemangleContextInnerBarrier<'ctx, 'a, W>
771 where
772 W: 'a + DemangleWrite,
773 'a: 'ctx,
774 {
deref_mut(&mut self) -> &mut Self::Target775 fn deref_mut(&mut self) -> &mut Self::Target {
776 self.ctx
777 }
778 }
779
780 impl<'ctx, 'a, W> Drop for AutoDemangleContextInnerBarrier<'ctx, 'a, W>
781 where
782 W: 'a + DemangleWrite,
783 'a: 'ctx,
784 {
drop(&mut self)785 fn drop(&mut self) {
786 // NB: We cannot assert that the context's inner is empty here,
787 // because if demangling failed we'll unwind the stack without
788 // using everything that put on the inner.
789 if !self.ctx.inner.is_empty() {
790 log!("Context inner was not emptied, did demangling fail?");
791 }
792 mem::swap(&mut self.saved_inner, &mut self.ctx.inner);
793 }
794 }
795
796 /// The inner stack allows passing AST nodes down deeper into the tree so that
797 /// nodes that logically precede something (e.g. PointerRef) can show up after
798 /// that thing in the demangled output. What's on the stack may not always be
799 /// intended for the first node that looks at the stack to grab, though.
800 ///
801 /// Consider a function with template arguments and parameters, f<T>(a).
802 /// The function parameters logically precede the template arguments in the AST,
803 /// but they must be reversed in the output. The parameters end up on the inner
804 /// stack before processing the template argument nodes. If we're not careful,
805 /// a node inside the template arguments might pick the function parameters
806 /// off of the inner stack!
807 ///
808 /// To solve this, certain nodes act as "inner barriers". By using this macro,
809 /// they set the existing inner stack aside and replace it with an empty stack
810 /// while visiting their children. This allows these barrier nodes to have
811 /// completely self-contained children.
812 macro_rules! inner_barrier {
813 ( $ctx:ident ) => {
814 let mut _ctx = AutoDemangleContextInnerBarrier::new($ctx);
815 let $ctx = &mut _ctx;
816 }
817 }
818
819 /// Any AST node that can be printed in a demangled form.
820 #[doc(hidden)]
821 pub trait Demangle<'subs, W>: fmt::Debug
822 where
823 W: 'subs + DemangleWrite,
824 {
825 /// Write the demangled form of this AST node to the given context.
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result826 fn demangle<'prev, 'ctx>(
827 &'subs self,
828 ctx: &'ctx mut DemangleContext<'subs, W>,
829 scope: Option<ArgScopeStack<'prev, 'subs>>,
830 ) -> fmt::Result;
831 }
832
833 /// Any AST node that can be printed as an inner type.
834 ///
835 /// See the comments surrounding `DemangleContext::inner` for details.
836 #[doc(hidden)]
837 pub trait DemangleAsInner<'subs, W>: Demangle<'subs, W>
838 where
839 W: 'subs + DemangleWrite,
840 {
841 /// Write the inner demangling form of this AST node to the given context.
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result842 fn demangle_as_inner<'prev, 'ctx>(
843 &'subs self,
844 ctx: &'ctx mut DemangleContext<'subs, W>,
845 scope: Option<ArgScopeStack<'prev, 'subs>>,
846 ) -> fmt::Result {
847 self.demangle(ctx, scope)
848 }
849
850 /// Cast this `DemangleAsInner` to a `Type`.
downcast_to_type(&self) -> Option<&Type>851 fn downcast_to_type(&self) -> Option<&Type> {
852 None
853 }
854
855 /// Cast this `DemangleAsInner` to a `FunctionType`.
downcast_to_function_type(&self) -> Option<&FunctionType>856 fn downcast_to_function_type(&self) -> Option<&FunctionType> {
857 None
858 }
859
860 /// Cast this `DemangleAsInner` to an `ArrayType`.
downcast_to_array_type(&self) -> Option<&ArrayType>861 fn downcast_to_array_type(&self) -> Option<&ArrayType> {
862 None
863 }
864
865 /// Cast this `DemangleAsInner` to a `PointerToMember`.
downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType>866 fn downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType> {
867 None
868 }
869
is_qualified(&self) -> bool870 fn is_qualified(&self) -> bool {
871 false
872 }
873 }
874
875 /// Demangle this thing in the leaf name position.
876 ///
877 /// For most things this should be the same as its `Demangle`
878 /// implementation. For `WellKnownComponent`s we need to strip the embedded
879 /// `std::` namespace prefix.
880 pub(crate) trait DemangleAsLeaf<'subs, W>
881 where
882 W: 'subs + DemangleWrite,
883 {
demangle_as_leaf<'me, 'ctx>( &'me self, ctx: &'ctx mut DemangleContext<'subs, W>, ) -> fmt::Result884 fn demangle_as_leaf<'me, 'ctx>(
885 &'me self,
886 ctx: &'ctx mut DemangleContext<'subs, W>,
887 ) -> fmt::Result;
888 }
889
890 macro_rules! reference_newtype {
891 ( $newtype_name:ident , $oldtype:ty ) => {
892 #[derive(Debug)]
893 struct $newtype_name($oldtype);
894
895 impl $newtype_name {
896 #[allow(clippy::ptr_arg)]
897 #[allow(unsafe_code)]
898 fn new(types: &$oldtype) -> &$newtype_name {
899 unsafe {
900 // This is safe because we only create an immutable
901 // reference. We are not breaking unique mutable aliasing
902 // requirements. An immutable reference does not allow
903 // dropping the referent, so no worries about double-free
904 // (additionally, see the assertion inside `Drop` below).
905 &*(types as *const $oldtype as *const $newtype_name)
906 }
907 }
908 }
909
910 impl Drop for $newtype_name {
911 fn drop(&mut self) {
912 unreachable!("Dropping implies we dereferenced and took ownership, which \
913 is not safe for this newtype");
914 }
915 }
916
917 impl ops::Deref for $newtype_name {
918 type Target = $oldtype;
919
920 fn deref(&self) -> &Self::Target {
921 &self.0
922 }
923 }
924 }
925 }
926
927 // We can't implement `DemangleAsInner` for newtypes of `[TypeHandle]` like we
928 // want to because it is unsized and we need to make trait objects out of
929 // `DemangleAsInner` for pushing onto the context's inner stack. Therefore, we
930 // have this inelegant newtyping of `Vec<TypeHandle>`.
931
932 // A set of function arguments.
933 reference_newtype!(FunctionArgList, Vec<TypeHandle>);
934
935 // A set of function arguments prefixed by a return type (which we want to
936 // ignore).
937 reference_newtype!(FunctionArgListAndReturnType, Vec<TypeHandle>);
938
939 // A newtype around a slice of type handles that we format as function
940 // arguments.
941 reference_newtype!(FunctionArgSlice, [TypeHandle]);
942
943 // Demangle a slice of TypeHandle as a function argument list.
944 impl<'subs, W> Demangle<'subs, W> for FunctionArgSlice
945 where
946 W: 'subs + DemangleWrite,
947 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result948 fn demangle<'prev, 'ctx>(
949 &'subs self,
950 ctx: &'ctx mut DemangleContext<'subs, W>,
951 scope: Option<ArgScopeStack<'prev, 'subs>>,
952 ) -> fmt::Result {
953 let ctx = try_begin_demangle!(self, ctx, scope);
954
955 let mut saw_needs_paren = false;
956 let (needs_space, needs_paren) = ctx.inner
957 .iter()
958 .rev()
959 .map(|inner| {
960 if inner.downcast_to_pointer_to_member().is_some() {
961 (true, true)
962 } else {
963 match inner.downcast_to_type() {
964 Some(&Type::Qualified(..))
965 | Some(&Type::Complex(_))
966 | Some(&Type::Imaginary(_))
967 | Some(&Type::PointerToMember(_)) => (true, true),
968 Some(&Type::PointerTo(_))
969 | Some(&Type::LvalueRef(_))
970 | Some(&Type::RvalueRef(_)) => (false, true),
971 _ => (false, false),
972 }
973 }
974 })
975 .take_while(|&(_, needs_paren)| {
976 if saw_needs_paren {
977 false
978 } else {
979 saw_needs_paren |= needs_paren;
980 true
981 }
982 })
983 .fold((false, false), |(space, paren), (next_space, next_paren)| {
984 (space || next_space, paren || next_paren)
985 });
986
987 if needs_paren {
988 let needs_space = needs_space || match ctx.last_char_written {
989 Some('(') | Some('*') => false,
990 _ => true,
991 };
992
993 if needs_space {
994 ctx.ensure_space()?;
995 }
996
997 write!(ctx, "(")?;
998 }
999
1000 ctx.demangle_inner_prefixes(scope)?;
1001
1002 if needs_paren {
1003 write!(ctx, ")")?;
1004 }
1005
1006 write!(ctx, "(")?;
1007
1008 // To maintain compatibility with libiberty, print `()` instead of
1009 // `(void)` for functions that take no arguments.
1010 if self.len() == 1 && self[0].is_void() {
1011 write!(ctx, ")")?;
1012 return Ok(());
1013 }
1014
1015 let mut need_comma = false;
1016 for arg in self.iter() {
1017 if need_comma {
1018 write!(ctx, ", ")?;
1019 }
1020 arg.demangle(ctx, scope)?;
1021 need_comma = true;
1022 }
1023
1024 write!(ctx, ")")?;
1025
1026 ctx.demangle_inners(scope)
1027 }
1028 }
1029
1030 impl<'subs, W> Demangle<'subs, W> for FunctionArgList
1031 where
1032 W: 'subs + DemangleWrite,
1033 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1034 fn demangle<'prev, 'ctx>(
1035 &'subs self,
1036 ctx: &'ctx mut DemangleContext<'subs, W>,
1037 scope: Option<ArgScopeStack<'prev, 'subs>>,
1038 ) -> fmt::Result {
1039 FunctionArgSlice::new(&self.0[..]).demangle(ctx, scope)
1040 }
1041 }
1042
1043 impl<'subs, W> DemangleAsInner<'subs, W> for FunctionArgList
1044 where
1045 W: 'subs + DemangleWrite,
1046 {
1047 }
1048
1049 impl<'subs, W> Demangle<'subs, W> for FunctionArgListAndReturnType
1050 where
1051 W: 'subs + DemangleWrite,
1052 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1053 fn demangle<'prev, 'ctx>(
1054 &'subs self,
1055 ctx: &'ctx mut DemangleContext<'subs, W>,
1056 scope: Option<ArgScopeStack<'prev, 'subs>>,
1057 ) -> fmt::Result {
1058 FunctionArgSlice::new(&self.0[1..]).demangle(ctx, scope)
1059 }
1060 }
1061
1062 impl<'subs, W> DemangleAsInner<'subs, W> for FunctionArgListAndReturnType
1063 where
1064 W: 'subs + DemangleWrite,
1065 {
1066 }
1067
1068 /// Define a handle to a AST type that lives inside the substitution table. A
1069 /// handle is always either an index into the substitution table, or it is a
1070 /// reference to a "well-known" component.
1071 ///
1072 /// This declares:
1073 ///
1074 /// - The enum of either a back reference into the substitution table or a
1075 /// reference to a "well-known" component
1076 /// - a `Demangle` impl that proxies to the appropriate `Substitutable` in the
1077 /// `SubstitutionTable`
1078 macro_rules! define_handle {
1079 (
1080 $(#[$attr:meta])*
1081 pub enum $typename:ident
1082 ) => {
1083 define_handle! {
1084 $(#[$attr])*
1085 pub enum $typename {}
1086 }
1087 };
1088
1089 (
1090 $(#[$attr:meta])*
1091 pub enum $typename:ident {
1092 $(
1093 $( #[$extra_attr:meta] )*
1094 extra $extra_variant:ident ( $extra_variant_ty:ty ),
1095 )*
1096 }
1097 ) => {
1098 $(#[$attr])*
1099 #[derive(Clone, Debug, PartialEq, Eq)]
1100 pub enum $typename {
1101 /// A reference to a "well-known" component.
1102 WellKnown(WellKnownComponent),
1103
1104 /// A back-reference into the substitution table to a component we
1105 /// have already parsed.
1106 BackReference(usize),
1107
1108 $(
1109 $( #[$extra_attr] )*
1110 $extra_variant( $extra_variant_ty ),
1111 )*
1112 }
1113
1114 impl $typename {
1115 /// If this is a `BackReference`, get its index.
1116 pub fn back_reference(&self) -> Option<usize> {
1117 match *self {
1118 $typename::BackReference(n) => Some(n),
1119 _ => None,
1120 }
1121 }
1122 }
1123
1124 impl<'subs, W> Demangle<'subs, W> for $typename
1125 where
1126 W: 'subs + DemangleWrite
1127 {
1128 #[inline]
1129 fn demangle<'prev, 'ctx>(&'subs self,
1130 ctx: &'ctx mut DemangleContext<'subs, W>,
1131 scope: Option<ArgScopeStack<'prev, 'subs>>)
1132 -> fmt::Result {
1133 match *self {
1134 $typename::WellKnown(ref comp) => comp.demangle(ctx, scope),
1135 $typename::BackReference(idx) => ctx.subs[idx].demangle(ctx, scope),
1136 $(
1137 $typename::$extra_variant(ref extra) => extra.demangle(ctx, scope),
1138 )*
1139 }
1140 }
1141 }
1142
1143 impl<'a> GetLeafName<'a> for $typename {
1144 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1145 match *self {
1146 $typename::WellKnown(ref wk) => wk.get_leaf_name(subs),
1147 $typename::BackReference(idx) => {
1148 subs.get(idx).and_then(|s| s.get_leaf_name(subs))
1149 }
1150 $(
1151 $typename::$extra_variant(ref e) => e.get_leaf_name(subs),
1152 )*
1153 }
1154 }
1155 }
1156 };
1157 }
1158
1159 /// A handle to a component that is usually substitutable, and lives in the
1160 /// substitutions table, but in this particular case does not qualify for
1161 /// substitutions.
1162 #[derive(Clone, Debug, PartialEq, Eq)]
1163 pub struct NonSubstitution(usize);
1164
1165 impl<'subs, W> Demangle<'subs, W> for NonSubstitution
1166 where
1167 W: 'subs + DemangleWrite,
1168 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1169 fn demangle<'prev, 'ctx>(
1170 &'subs self,
1171 ctx: &'ctx mut DemangleContext<'subs, W>,
1172 scope: Option<ArgScopeStack<'prev, 'subs>>,
1173 ) -> fmt::Result {
1174 ctx.subs.non_substitution(self.0).demangle(ctx, scope)
1175 }
1176 }
1177
1178 impl<'a> GetLeafName<'a> for NonSubstitution {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>1179 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1180 subs.get_non_substitution(self.0)
1181 .and_then(|ns| ns.get_leaf_name(subs))
1182 }
1183 }
1184
1185 /// Define a "vocabulary" nonterminal, something like `OperatorName` or
1186 /// `CtorDtorName` that's basically a big list of constant strings.
1187 ///
1188 /// This declares:
1189 ///
1190 /// - the enum itself
1191 /// - a `Parse` impl
1192 /// - a `Demangle` impl
1193 ///
1194 /// See the definition of `CTorDtorName` for an example of its use.
1195 ///
1196 /// Optionally, a piece of user data can be attached to the definitions
1197 /// and be returned by a generated accessor. See `SimpleOperatorName` for
1198 /// an example.
1199 macro_rules! define_vocabulary {
1200 ( $(#[$attr:meta])* pub enum $typename:ident {
1201 $($variant:ident ( $mangled:expr, $printable:expr )),*
1202 } ) => {
1203
1204 $(#[$attr])*
1205 pub enum $typename {
1206 $(
1207 #[doc=$printable]
1208 $variant
1209 ),*
1210 }
1211
1212 impl Parse for $typename {
1213 fn parse<'a, 'b>(ctx: &'a ParseContext,
1214 _subs: &'a mut SubstitutionTable,
1215 input: IndexStr<'b>)
1216 -> Result<($typename, IndexStr<'b>)> {
1217 try_begin_parse!(stringify!($typename), ctx, input);
1218
1219 let mut found_prefix = false;
1220 $(
1221 if let Some((head, tail)) = input.try_split_at($mangled.len()) {
1222 if head.as_ref() == $mangled {
1223 return Ok(($typename::$variant, tail));
1224 }
1225 } else {
1226 found_prefix |= 0 < input.len() &&
1227 input.len() < $mangled.len() &&
1228 input.as_ref() == &$mangled[..input.len()];
1229 }
1230 )*
1231
1232 if input.is_empty() || found_prefix {
1233 Err(error::Error::UnexpectedEnd)
1234 } else {
1235 Err(error::Error::UnexpectedText)
1236 }
1237 }
1238 }
1239
1240 impl<'subs, W> Demangle<'subs, W> for $typename
1241 where
1242 W: 'subs + DemangleWrite,
1243 {
1244 fn demangle<'prev, 'ctx>(
1245 &'subs self,
1246 ctx: &'ctx mut DemangleContext<'subs, W>,
1247 scope: Option<ArgScopeStack<'prev, 'subs>>
1248 ) -> fmt::Result {
1249 let ctx = try_begin_demangle!(self, ctx, scope);
1250
1251 write!(ctx, "{}", match *self {
1252 $(
1253 $typename::$variant => $printable
1254 ),*
1255 })
1256 }
1257 }
1258
1259 impl $typename {
1260 #[allow(dead_code)]
1261 #[inline]
1262 fn starts_with(byte: u8) -> bool {
1263 $(
1264 if $mangled[0] == byte {
1265 return true;
1266 }
1267 )*
1268
1269 false
1270 }
1271 }
1272 };
1273 ( $(#[$attr:meta])* pub enum $typename:ident {
1274 $($variant:ident ( $mangled:expr, $printable:expr, $userdata:expr)),*
1275 }
1276
1277 impl $typename2:ident {
1278 fn $fn_name:ident(&self) -> $userdata_ty:ty;
1279 } ) => {
1280 define_vocabulary! {
1281 $(#[$attr])*
1282 pub enum $typename {
1283 $(
1284 $variant ( $mangled, $printable )
1285 ),*
1286 }
1287 }
1288
1289 impl $typename2 {
1290 fn $fn_name(&self) -> $userdata_ty {
1291 match *self {
1292 $(
1293 $typename2::$variant => $userdata,
1294 )*
1295 }
1296 }
1297 }
1298 };
1299 }
1300
1301 /// The root AST node, and starting production.
1302 ///
1303 /// ```text
1304 /// <mangled-name> ::= _Z <encoding> [<clone-suffix>]*
1305 /// ::= ___Z <encoding> <block_invoke>
1306 /// ::= <type>
1307 ///
1308 /// <block_invoke> ::= _block_invoke
1309 /// ::= _block_invoke<decimal-digit>+
1310 /// ::= _block_invoke_<decimal-digit>+
1311 /// ```
1312 #[derive(Clone, Debug, PartialEq, Eq)]
1313 pub enum MangledName {
1314 /// The encoding of the mangled symbol name.
1315 Encoding(Encoding, Vec<CloneSuffix>),
1316
1317 /// The encoding of the mangled symbol name.
1318 BlockInvoke(Encoding, Option<isize>),
1319
1320 /// A top-level type. Technically not allowed by the standard, however in
1321 /// practice this can happen, and is tested for by libiberty.
1322 Type(TypeHandle),
1323
1324 /// A global constructor or destructor. This is another de facto standard
1325 /// extension (I think originally from `g++`?) that is not actually part of
1326 /// the standard proper.
1327 GlobalCtorDtor(GlobalCtorDtor),
1328 }
1329
1330 impl Parse for MangledName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(MangledName, IndexStr<'b>)>1331 fn parse<'a, 'b>(
1332 ctx: &'a ParseContext,
1333 subs: &'a mut SubstitutionTable,
1334 input: IndexStr<'b>,
1335 ) -> Result<(MangledName, IndexStr<'b>)> {
1336 try_begin_parse!("MangledName", ctx, input);
1337
1338 if let Ok(tail) = consume(b"_Z", input).or_else(|_| consume(b"__Z", input)) {
1339 let (encoding, tail) = Encoding::parse(ctx, subs, tail)?;
1340 let (clone_suffixes, tail) = zero_or_more(ctx, subs, tail)?;
1341 return Ok((MangledName::Encoding(encoding, clone_suffixes), tail));
1342 }
1343
1344 if let Ok(tail) = consume(b"___Z", input).or_else(|_| consume(b"____Z", input)) {
1345 let (encoding, tail) = Encoding::parse(ctx, subs, tail)?;
1346 let tail = consume(b"_block_invoke", tail)?;
1347
1348 let tail_opt = match consume(b"_", tail) {
1349 Ok(tail) => Some(parse_number(10, false, tail)?),
1350 Err(_) => parse_number(10, false, tail).ok(),
1351 };
1352
1353 let (digits, tail) = match tail_opt {
1354 Some((digits, tail)) => (Some(digits), tail),
1355 None => (None, tail),
1356 };
1357
1358 return Ok((MangledName::BlockInvoke(encoding, digits), tail));
1359 }
1360
1361 if let Ok(tail) = consume(b"_GLOBAL_", input) {
1362 let (global_ctor_dtor, tail) = GlobalCtorDtor::parse(ctx, subs, tail)?;
1363 return Ok((MangledName::GlobalCtorDtor(global_ctor_dtor), tail));
1364 }
1365
1366 // The libiberty tests also specify that a type can be top level,
1367 // and they are not prefixed with "_Z".
1368 let (ty, tail) = TypeHandle::parse(ctx, subs, input)?;
1369 Ok((MangledName::Type(ty), tail))
1370 }
1371 }
1372
1373 impl<'subs, W> Demangle<'subs, W> for MangledName
1374 where
1375 W: 'subs + DemangleWrite,
1376 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1377 fn demangle<'prev, 'ctx>(
1378 &'subs self,
1379 ctx: &'ctx mut DemangleContext<'subs, W>,
1380 scope: Option<ArgScopeStack<'prev, 'subs>>,
1381 ) -> fmt::Result {
1382 let ctx = try_begin_demangle!(self, ctx, scope);
1383
1384 match *self {
1385 MangledName::Encoding(ref enc, ref cs) => {
1386 enc.demangle(ctx, scope)?;
1387 if !cs.is_empty() && ctx.show_params {
1388 for clone_suffix in cs {
1389 clone_suffix.demangle(ctx, scope)?;
1390 }
1391 }
1392 Ok(())
1393 },
1394 MangledName::BlockInvoke(ref enc, _) => {
1395 write!(ctx, "invocation function for block in ")?;
1396 enc.demangle(ctx, scope)?;
1397 Ok(())
1398 }
1399 MangledName::Type(ref ty) => ty.demangle(ctx, scope),
1400 MangledName::GlobalCtorDtor(ref gcd) => gcd.demangle(ctx, scope),
1401 }
1402 }
1403 }
1404
1405 /// The `<encoding>` production.
1406 ///
1407 /// ```text
1408 /// <encoding> ::= <function name> <bare-function-type>
1409 /// ::= <data name>
1410 /// ::= <special-name>
1411 /// ```
1412 #[derive(Clone, Debug, PartialEq, Eq)]
1413 pub enum Encoding {
1414 /// An encoded function.
1415 Function(Name, BareFunctionType),
1416
1417 /// An encoded static variable.
1418 Data(Name),
1419
1420 /// A special encoding.
1421 Special(SpecialName),
1422 }
1423
1424 impl Parse for Encoding {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Encoding, IndexStr<'b>)>1425 fn parse<'a, 'b>(
1426 ctx: &'a ParseContext,
1427 subs: &'a mut SubstitutionTable,
1428 input: IndexStr<'b>,
1429 ) -> Result<(Encoding, IndexStr<'b>)> {
1430 try_begin_parse!("Encoding", ctx, input);
1431
1432 if let Ok((name, tail)) = Name::parse(ctx, subs, input) {
1433 if let Ok((ty, tail)) = BareFunctionType::parse(ctx, subs, tail) {
1434 return Ok((Encoding::Function(name, ty), tail));
1435 } else {
1436 return Ok((Encoding::Data(name), tail));
1437 }
1438 }
1439
1440 let (name, tail) = SpecialName::parse(ctx, subs, input)?;
1441 Ok((Encoding::Special(name), tail))
1442 }
1443 }
1444
1445 impl<'subs, W> Demangle<'subs, W> for Encoding
1446 where
1447 W: 'subs + DemangleWrite,
1448 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1449 fn demangle<'prev, 'ctx>(
1450 &'subs self,
1451 ctx: &'ctx mut DemangleContext<'subs, W>,
1452 scope: Option<ArgScopeStack<'prev, 'subs>>,
1453 ) -> fmt::Result {
1454 let ctx = try_begin_demangle!(self, ctx, scope);
1455 inner_barrier!(ctx);
1456
1457 match *self {
1458 Encoding::Function(ref name, ref fun_ty) => {
1459 // Even if this function takes no args and doesn't have a return
1460 // value (see below), it will have the void parameter.
1461 debug_assert!(!fun_ty.0.is_empty());
1462
1463 let scope = if let Some(leaf) = name.get_leaf_name(ctx.subs) {
1464 match leaf {
1465 LeafName::SourceName(leaf) => scope.push(leaf),
1466 LeafName::WellKnownComponent(leaf) => scope.push(leaf),
1467 LeafName::Closure(leaf) => scope.push(leaf),
1468 LeafName::UnnamedType(leaf) => scope.push(leaf),
1469 }
1470 } else {
1471 scope
1472 };
1473
1474 // Whether the first type in the BareFunctionType is a return
1475 // type or parameter depends on the context in which it
1476 // appears.
1477 //
1478 // * Templates and functions in a type or parameter position
1479 // have return types, unless they are constructors, destructors,
1480 // or conversion operator functions.
1481 //
1482 // * Non-template functions that are not in a type or parameter
1483 // position do not have a return type.
1484 //
1485 // We know we are not printing a type, so we only need to check
1486 // whether this is a template.
1487 //
1488 // For the details, see
1489 // http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.function-type
1490 let scope = if let Some(template_args) = name.get_template_args(ctx.subs) {
1491 let scope = scope.push(template_args);
1492 if ctx.show_return_type && !name.is_ctor_dtor_conversion(ctx.subs) {
1493 fun_ty.0[0].demangle(ctx, scope)?;
1494 write!(ctx, " ")?;
1495 }
1496
1497 scope
1498 } else {
1499 scope
1500 };
1501
1502 if ctx.show_params {
1503 ctx.push_inner(self);
1504 name.demangle(ctx, scope)?;
1505 if ctx.pop_inner_if(self) {
1506 self.demangle_as_inner(ctx, scope)?;
1507 }
1508 } else {
1509 name.demangle(ctx, scope)?;
1510 }
1511
1512 Ok(())
1513 }
1514 Encoding::Data(ref name) => name.demangle(ctx, scope),
1515 Encoding::Special(ref name) => name.demangle(ctx, scope),
1516 }
1517 }
1518 }
1519
1520 impl<'subs, W> DemangleAsInner<'subs, W> for Encoding
1521 where
1522 W: 'subs + DemangleWrite,
1523 {
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1524 fn demangle_as_inner<'prev, 'ctx>(
1525 &'subs self,
1526 ctx: &'ctx mut DemangleContext<'subs, W>,
1527 scope: Option<ArgScopeStack<'prev, 'subs>>,
1528 ) -> fmt::Result {
1529 if let Encoding::Function(ref name, ref fun_ty) = *self {
1530 let (scope, function_args) =
1531 if let Some(template_args) = name.get_template_args(ctx.subs) {
1532 let scope = scope.push(template_args);
1533 let function_args = FunctionArgListAndReturnType::new(&fun_ty.0);
1534 (scope, function_args as &dyn DemangleAsInner<W>)
1535 } else {
1536 let function_args = FunctionArgList::new(&fun_ty.0);
1537 (scope, function_args as &dyn DemangleAsInner<W>)
1538 };
1539 function_args.demangle_as_inner(ctx, scope)
1540 } else {
1541 unreachable!("we only push Encoding::Function onto the inner stack");
1542 }
1543 }
1544 }
1545
1546 /// <clone-suffix> ::= [ . <clone-type-identifier> ] [ . <nonnegative number> ]*
1547
1548 #[derive(Clone, Debug, PartialEq, Eq)]
1549 pub struct CloneSuffix(CloneTypeIdentifier, Vec<isize>);
1550
1551 impl Parse for CloneSuffix {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(CloneSuffix, IndexStr<'b>)>1552 fn parse<'a, 'b>(
1553 ctx: &'a ParseContext,
1554 subs: &'a mut SubstitutionTable,
1555 input: IndexStr<'b>,
1556 ) -> Result<(CloneSuffix, IndexStr<'b>)> {
1557 try_begin_parse!("CloneSuffix", ctx, input);
1558
1559 let tail = consume(b".", input)?;
1560 let (identifier, mut tail) = CloneTypeIdentifier::parse(ctx, subs, tail)?;
1561
1562 let mut numbers = Vec::with_capacity(1);
1563 while let Ok((n, t)) = consume(b".", tail).and_then(|t| parse_number(10, false, t)) {
1564 numbers.push(n);
1565 tail = t;
1566 }
1567
1568 let clone_suffix = CloneSuffix(identifier, numbers);
1569 Ok((clone_suffix, tail))
1570 }
1571 }
1572
1573 impl<'subs, W> Demangle<'subs, W> for CloneSuffix
1574 where
1575 W: 'subs + DemangleWrite,
1576 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1577 fn demangle<'prev, 'ctx>(
1578 &'subs self,
1579 ctx: &'ctx mut DemangleContext<'subs, W>,
1580 scope: Option<ArgScopeStack<'prev, 'subs>>,
1581 ) -> fmt::Result {
1582 let ctx = try_begin_demangle!(self, ctx, scope);
1583 write!(ctx, " [clone")?;
1584 self.0.demangle(ctx, scope)?;
1585 for nonnegative in &self.1 {
1586 write!(ctx, ".{}", nonnegative)?;
1587 }
1588 write!(ctx, "]")?;
1589 Ok(())
1590 }
1591 }
1592
1593 /// A global constructor or destructor.
1594 #[derive(Clone, Debug, PartialEq, Eq)]
1595 pub enum GlobalCtorDtor {
1596 /// A global constructor.
1597 Ctor(Box<MangledName>),
1598 /// A global destructor.
1599 Dtor(Box<MangledName>),
1600 }
1601
1602 impl Parse for GlobalCtorDtor {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(GlobalCtorDtor, IndexStr<'b>)>1603 fn parse<'a, 'b>(
1604 ctx: &'a ParseContext,
1605 subs: &'a mut SubstitutionTable,
1606 input: IndexStr<'b>,
1607 ) -> Result<(GlobalCtorDtor, IndexStr<'b>)> {
1608 try_begin_parse!("GlobalCtorDtor", ctx, input);
1609
1610 let tail = match input.next_or(error::Error::UnexpectedEnd)? {
1611 (b'_', t) | (b'.', t) | (b'$', t) => t,
1612 _ => return Err(error::Error::UnexpectedText),
1613 };
1614
1615 match tail.next_or(error::Error::UnexpectedEnd)? {
1616 (b'I', tail) => {
1617 let tail = consume(b"_", tail)?;
1618 let (name, tail) = MangledName::parse(ctx, subs, tail)?;
1619 Ok((GlobalCtorDtor::Ctor(Box::new(name)), tail))
1620 }
1621 (b'D', tail) => {
1622 let tail = consume(b"_", tail)?;
1623 let (name, tail) = MangledName::parse(ctx, subs, tail)?;
1624 Ok((GlobalCtorDtor::Dtor(Box::new(name)), tail))
1625 }
1626 _ => Err(error::Error::UnexpectedText),
1627 }
1628 }
1629 }
1630
1631 impl<'subs, W> Demangle<'subs, W> for GlobalCtorDtor
1632 where
1633 W: 'subs + DemangleWrite,
1634 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1635 fn demangle<'prev, 'ctx>(
1636 &'subs self,
1637 ctx: &'ctx mut DemangleContext<'subs, W>,
1638 scope: Option<ArgScopeStack<'prev, 'subs>>,
1639 ) -> fmt::Result {
1640 let ctx = try_begin_demangle!(self, ctx, scope);
1641 inner_barrier!(ctx);
1642
1643 let saved_show_params = ctx.show_params;
1644 ctx.show_params = true;
1645 let ret = match *self {
1646 GlobalCtorDtor::Ctor(ref name) => {
1647 write!(ctx, "global constructors keyed to ")?;
1648 name.demangle(ctx, scope)
1649 }
1650 GlobalCtorDtor::Dtor(ref name) => {
1651 write!(ctx, "global destructors keyed to ")?;
1652 name.demangle(ctx, scope)
1653 }
1654 };
1655 ctx.show_params = saved_show_params;
1656 ret
1657 }
1658 }
1659
1660 /// The `<name>` production.
1661 ///
1662 /// ```text
1663 /// <name> ::= <nested-name>
1664 /// ::= <unscoped-name>
1665 /// ::= <unscoped-template-name> <template-args>
1666 /// ::= <local-name>
1667 /// ```
1668 #[derive(Clone, Debug, PartialEq, Eq)]
1669 pub enum Name {
1670 /// A nested name
1671 Nested(NestedName),
1672
1673 /// An unscoped name.
1674 Unscoped(UnscopedName),
1675
1676 /// An unscoped template.
1677 UnscopedTemplate(UnscopedTemplateNameHandle, TemplateArgs),
1678
1679 /// A local name.
1680 Local(LocalName),
1681 }
1682
1683 impl Parse for Name {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Name, IndexStr<'b>)>1684 fn parse<'a, 'b>(
1685 ctx: &'a ParseContext,
1686 subs: &'a mut SubstitutionTable,
1687 input: IndexStr<'b>,
1688 ) -> Result<(Name, IndexStr<'b>)> {
1689 try_begin_parse!("Name", ctx, input);
1690
1691 if let Ok((name, tail)) = NestedName::parse(ctx, subs, input) {
1692 return Ok((Name::Nested(name), tail));
1693 }
1694
1695 if let Ok((name, tail)) = UnscopedName::parse(ctx, subs, input) {
1696 if tail.peek() == Some(b'I') {
1697 let name = UnscopedTemplateName(name);
1698 let idx = subs.insert(Substitutable::UnscopedTemplateName(name));
1699 let handle = UnscopedTemplateNameHandle::BackReference(idx);
1700
1701 let (args, tail) = TemplateArgs::parse(ctx, subs, tail)?;
1702 return Ok((Name::UnscopedTemplate(handle, args), tail));
1703 } else {
1704 return Ok((Name::Unscoped(name), tail));
1705 }
1706 }
1707
1708 if let Ok((name, tail)) = UnscopedTemplateNameHandle::parse(ctx, subs, input) {
1709 let (args, tail) = TemplateArgs::parse(ctx, subs, tail)?;
1710 return Ok((Name::UnscopedTemplate(name, args), tail));
1711 }
1712
1713 let (name, tail) = LocalName::parse(ctx, subs, input)?;
1714 Ok((Name::Local(name), tail))
1715 }
1716 }
1717
1718 impl<'subs, W> Demangle<'subs, W> for Name
1719 where
1720 W: 'subs + DemangleWrite,
1721 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1722 fn demangle<'prev, 'ctx>(
1723 &'subs self,
1724 ctx: &'ctx mut DemangleContext<'subs, W>,
1725 scope: Option<ArgScopeStack<'prev, 'subs>>,
1726 ) -> fmt::Result {
1727 let ctx = try_begin_demangle!(self, ctx, scope);
1728
1729 match *self {
1730 Name::Nested(ref nested) => nested.demangle(ctx, scope),
1731 Name::Unscoped(ref unscoped) => unscoped.demangle(ctx, scope),
1732 Name::UnscopedTemplate(ref template, ref args) => {
1733 template.demangle(ctx, scope.push(args))?;
1734 args.demangle(ctx, scope)
1735 }
1736 Name::Local(ref local) => local.demangle(ctx, scope),
1737 }
1738 }
1739 }
1740
1741 impl GetTemplateArgs for Name {
get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>1742 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
1743 match *self {
1744 Name::UnscopedTemplate(_, ref args) => Some(args),
1745 Name::Nested(ref nested) => nested.get_template_args(subs),
1746 Name::Local(ref local) => local.get_template_args(subs),
1747 Name::Unscoped(_) => None,
1748 }
1749 }
1750 }
1751
1752 impl<'a> GetLeafName<'a> for Name {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>1753 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1754 match *self {
1755 Name::UnscopedTemplate(ref templ, _) => templ.get_leaf_name(subs),
1756 Name::Nested(ref nested) => nested.get_leaf_name(subs),
1757 Name::Unscoped(ref unscoped) => unscoped.get_leaf_name(subs),
1758 Name::Local(ref local) => local.get_leaf_name(subs),
1759 }
1760 }
1761 }
1762
1763 impl IsCtorDtorConversion for Name {
is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool1764 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
1765 match *self {
1766 Name::Unscoped(ref unscoped) => unscoped.is_ctor_dtor_conversion(subs),
1767 Name::Nested(ref nested) => nested.is_ctor_dtor_conversion(subs),
1768 Name::Local(_) |
1769 Name::UnscopedTemplate(..) => false,
1770 }
1771 }
1772 }
1773
1774 /// The `<unscoped-name>` production.
1775 ///
1776 /// ```text
1777 /// <unscoped-name> ::= <unqualified-name>
1778 /// ::= St <unqualified-name> # ::std::
1779 /// ```
1780 #[derive(Clone, Debug, PartialEq, Eq)]
1781 pub enum UnscopedName {
1782 /// An unqualified name.
1783 Unqualified(UnqualifiedName),
1784
1785 /// A name within the `std::` namespace.
1786 Std(UnqualifiedName),
1787 }
1788
1789 impl Parse for UnscopedName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(UnscopedName, IndexStr<'b>)>1790 fn parse<'a, 'b>(
1791 ctx: &'a ParseContext,
1792 subs: &'a mut SubstitutionTable,
1793 input: IndexStr<'b>,
1794 ) -> Result<(UnscopedName, IndexStr<'b>)> {
1795 try_begin_parse!("UnscopedName", ctx, input);
1796
1797 if let Ok(tail) = consume(b"St", input) {
1798 let (name, tail) = UnqualifiedName::parse(ctx, subs, tail)?;
1799 return Ok((UnscopedName::Std(name), tail));
1800 }
1801
1802 let (name, tail) = UnqualifiedName::parse(ctx, subs, input)?;
1803 Ok((UnscopedName::Unqualified(name), tail))
1804 }
1805 }
1806
1807 impl<'subs, W> Demangle<'subs, W> for UnscopedName
1808 where
1809 W: 'subs + DemangleWrite,
1810 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1811 fn demangle<'prev, 'ctx>(
1812 &'subs self,
1813 ctx: &'ctx mut DemangleContext<'subs, W>,
1814 scope: Option<ArgScopeStack<'prev, 'subs>>,
1815 ) -> fmt::Result {
1816 let ctx = try_begin_demangle!(self, ctx, scope);
1817
1818 match *self {
1819 UnscopedName::Unqualified(ref unqualified) => unqualified.demangle(ctx, scope),
1820 UnscopedName::Std(ref std) => {
1821 write!(ctx, "std::")?;
1822 std.demangle(ctx, scope)
1823 }
1824 }
1825 }
1826 }
1827
1828 impl<'a> GetLeafName<'a> for UnscopedName {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>1829 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1830 match *self {
1831 UnscopedName::Unqualified(ref name) | UnscopedName::Std(ref name) => {
1832 name.get_leaf_name(subs)
1833 }
1834 }
1835 }
1836 }
1837
1838 impl IsCtorDtorConversion for UnscopedName {
is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool1839 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
1840 match *self {
1841 UnscopedName::Unqualified(ref name) | UnscopedName::Std(ref name) => name.is_ctor_dtor_conversion(subs),
1842 }
1843 }
1844 }
1845
1846 /// The `<unscoped-template-name>` production.
1847 ///
1848 /// ```text
1849 /// <unscoped-template-name> ::= <unscoped-name>
1850 /// ::= <substitution>
1851 /// ```
1852 #[derive(Clone, Debug, PartialEq, Eq)]
1853 pub struct UnscopedTemplateName(UnscopedName);
1854
1855 define_handle! {
1856 /// A handle to an `UnscopedTemplateName`.
1857 pub enum UnscopedTemplateNameHandle {
1858 /// A handle to some `<unscoped-name>` component that isn't by itself
1859 /// substitutable.
1860 extra NonSubstitution(NonSubstitution),
1861 }
1862 }
1863
1864 impl Parse for UnscopedTemplateNameHandle {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(UnscopedTemplateNameHandle, IndexStr<'b>)>1865 fn parse<'a, 'b>(
1866 ctx: &'a ParseContext,
1867 subs: &'a mut SubstitutionTable,
1868 input: IndexStr<'b>,
1869 ) -> Result<(UnscopedTemplateNameHandle, IndexStr<'b>)> {
1870 try_begin_parse!("UnscopedTemplateNameHandle", ctx, input);
1871
1872 if let Ok((name, tail)) = UnscopedName::parse(ctx, subs, input) {
1873 let name = UnscopedTemplateName(name);
1874 let idx = subs.insert(Substitutable::UnscopedTemplateName(name));
1875 let handle = UnscopedTemplateNameHandle::BackReference(idx);
1876 return Ok((handle, tail));
1877 }
1878
1879 let (sub, tail) = Substitution::parse(ctx, subs, input)?;
1880
1881 match sub {
1882 Substitution::WellKnown(component) => {
1883 Ok((UnscopedTemplateNameHandle::WellKnown(component), tail))
1884 }
1885 Substitution::BackReference(idx) => {
1886 // TODO: should this check/assert that subs[idx] is an
1887 // UnscopedTemplateName?
1888 Ok((UnscopedTemplateNameHandle::BackReference(idx), tail))
1889 }
1890 }
1891 }
1892 }
1893
1894 impl<'subs, W> Demangle<'subs, W> for UnscopedTemplateName
1895 where
1896 W: 'subs + DemangleWrite,
1897 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1898 fn demangle<'prev, 'ctx>(
1899 &'subs self,
1900 ctx: &'ctx mut DemangleContext<'subs, W>,
1901 scope: Option<ArgScopeStack<'prev, 'subs>>,
1902 ) -> fmt::Result {
1903 let ctx = try_begin_demangle!(self, ctx, scope);
1904
1905 self.0.demangle(ctx, scope)
1906 }
1907 }
1908
1909 impl<'a> GetLeafName<'a> for UnscopedTemplateName {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>1910 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1911 self.0.get_leaf_name(subs)
1912 }
1913 }
1914
1915 /// The `<nested-name>` production.
1916 ///
1917 /// ```text
1918 /// <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
1919 /// ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
1920 /// ```
1921 #[derive(Clone, Debug, PartialEq, Eq)]
1922 pub enum NestedName {
1923 /// A nested name.
1924 Unqualified(
1925 CvQualifiers,
1926 Option<RefQualifier>,
1927 PrefixHandle,
1928 UnqualifiedName,
1929 ),
1930
1931 /// A nested template name. The `<template-args>` are part of the `PrefixHandle`.
1932 Template(CvQualifiers, Option<RefQualifier>, PrefixHandle),
1933 }
1934
1935 impl Parse for NestedName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(NestedName, IndexStr<'b>)>1936 fn parse<'a, 'b>(
1937 ctx: &'a ParseContext,
1938 subs: &'a mut SubstitutionTable,
1939 input: IndexStr<'b>,
1940 ) -> Result<(NestedName, IndexStr<'b>)> {
1941 try_begin_parse!("NestedName", ctx, input);
1942
1943 let tail = consume(b"N", input)?;
1944
1945 let (cv_qualifiers, tail) = if let Ok((q, tail)) = CvQualifiers::parse(ctx, subs, tail) {
1946 (q, tail)
1947 } else {
1948 (Default::default(), tail)
1949 };
1950
1951 let (ref_qualifier, tail) = if let Ok((r, tail)) = RefQualifier::parse(ctx, subs, tail) {
1952 (Some(r), tail)
1953 } else {
1954 (None, tail)
1955 };
1956
1957 let (prefix, tail) = PrefixHandle::parse(ctx, subs, tail)?;
1958 let tail = consume(b"E", tail)?;
1959
1960 let substitutable = match prefix {
1961 PrefixHandle::BackReference(idx) => subs.get(idx),
1962 PrefixHandle::NonSubstitution(NonSubstitution(idx)) => subs.get_non_substitution(idx),
1963 PrefixHandle::WellKnown(_) => None,
1964 };
1965
1966 match substitutable {
1967 Some(&Substitutable::Prefix(Prefix::Nested(ref prefix, ref name))) => Ok((
1968 NestedName::Unqualified(cv_qualifiers, ref_qualifier, prefix.clone(), name.clone()),
1969 tail,
1970 )),
1971 Some(&Substitutable::Prefix(Prefix::Template(..))) => Ok((
1972 NestedName::Template(cv_qualifiers, ref_qualifier, prefix),
1973 tail,
1974 )),
1975 _ => Err(error::Error::UnexpectedText),
1976 }
1977 }
1978 }
1979
1980 impl NestedName {
1981 /// Get the CV-qualifiers for this name.
cv_qualifiers(&self) -> &CvQualifiers1982 pub fn cv_qualifiers(&self) -> &CvQualifiers {
1983 match *self {
1984 NestedName::Unqualified(ref q, ..) | NestedName::Template(ref q, ..) => q,
1985 }
1986 }
1987
1988 /// Get the ref-qualifier for this name, if one exists.
ref_qualifier(&self) -> Option<&RefQualifier>1989 pub fn ref_qualifier(&self) -> Option<&RefQualifier> {
1990 match *self {
1991 NestedName::Unqualified(_, Some(ref r), ..)
1992 | NestedName::Template(_, Some(ref r), ..) => Some(r),
1993 _ => None,
1994 }
1995 }
1996
1997 // Not public because the prefix means different things for different
1998 // variants, and for `::Template` it actually contains part of what
1999 // conceptually belongs to `<nested-name>`.
prefix(&self) -> &PrefixHandle2000 fn prefix(&self) -> &PrefixHandle {
2001 match *self {
2002 NestedName::Unqualified(_, _, ref p, _) | NestedName::Template(_, _, ref p) => p,
2003 }
2004 }
2005 }
2006
2007 impl<'subs, W> Demangle<'subs, W> for NestedName
2008 where
2009 W: 'subs + DemangleWrite,
2010 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result2011 fn demangle<'prev, 'ctx>(
2012 &'subs self,
2013 ctx: &'ctx mut DemangleContext<'subs, W>,
2014 scope: Option<ArgScopeStack<'prev, 'subs>>,
2015 ) -> fmt::Result {
2016 let ctx = try_begin_demangle!(self, ctx, scope);
2017
2018 match *self {
2019 NestedName::Unqualified(_, _, ref p, ref name) => {
2020 ctx.push_demangle_node(DemangleNodeType::NestedName);
2021 p.demangle(ctx, scope)?;
2022 if name.accepts_double_colon() {
2023 ctx.write_str("::")?;
2024 }
2025 name.demangle(ctx, scope)?;
2026 ctx.pop_demangle_node();
2027 }
2028 NestedName::Template(_, _, ref p) => {
2029 ctx.is_template_prefix_in_nested_name = true;
2030 p.demangle(ctx, scope)?;
2031 ctx.is_template_prefix_in_nested_name = false;
2032 }
2033 }
2034
2035 if let Some(inner) = ctx.pop_inner() {
2036 inner.demangle_as_inner(ctx, scope)?;
2037 }
2038
2039 if self.cv_qualifiers() != &CvQualifiers::default() && ctx.show_params {
2040 self.cv_qualifiers().demangle(ctx, scope)?;
2041 }
2042
2043 if let Some(ref refs) = self.ref_qualifier() {
2044 ctx.ensure_space()?;
2045 refs.demangle(ctx, scope)?;
2046 }
2047
2048 Ok(())
2049 }
2050 }
2051
2052 impl GetTemplateArgs for NestedName {
get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>2053 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
2054 match *self {
2055 NestedName::Template(_, _, ref prefix) => prefix.get_template_args(subs),
2056 _ => None,
2057 }
2058 }
2059 }
2060
2061 impl<'a> GetLeafName<'a> for NestedName {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>2062 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
2063 match *self {
2064 NestedName::Unqualified(_, _, ref prefix, ref name) => name.get_leaf_name(subs)
2065 .or_else(|| prefix.get_leaf_name(subs)),
2066 NestedName::Template(_, _, ref prefix) => prefix.get_leaf_name(subs),
2067 }
2068 }
2069 }
2070
2071 impl IsCtorDtorConversion for NestedName {
is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool2072 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
2073 self.prefix().is_ctor_dtor_conversion(subs)
2074 }
2075 }
2076
2077 /// The `<prefix>` production.
2078 ///
2079 /// ```text
2080 /// <prefix> ::= <unqualified-name>
2081 /// ::= <prefix> <unqualified-name>
2082 /// ::= <template-prefix> <template-args>
2083 /// ::= <template-param>
2084 /// ::= <decltype>
2085 /// ::= <prefix> <data-member-prefix>
2086 /// ::= <substitution>
2087 ///
2088 /// <template-prefix> ::= <template unqualified-name>
2089 /// ::= <prefix> <template unqualified-name>
2090 /// ::= <template-param>
2091 /// ::= <substitution>
2092 /// ```
2093 #[derive(Clone, Debug, PartialEq, Eq)]
2094 pub enum Prefix {
2095 /// An unqualified name.
2096 Unqualified(UnqualifiedName),
2097
2098 /// Some nested name.
2099 Nested(PrefixHandle, UnqualifiedName),
2100
2101 /// A prefix and template arguments.
2102 Template(PrefixHandle, TemplateArgs),
2103
2104 /// A template parameter.
2105 TemplateParam(TemplateParam),
2106
2107 /// A decltype.
2108 Decltype(Decltype),
2109
2110 /// A prefix and data member.
2111 DataMember(PrefixHandle, DataMemberPrefix),
2112 }
2113
2114 impl GetTemplateArgs for Prefix {
get_template_args<'a>(&'a self, _: &'a SubstitutionTable) -> Option<&'a TemplateArgs>2115 fn get_template_args<'a>(&'a self, _: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
2116 match *self {
2117 Prefix::Template(_, ref args) => Some(args),
2118 Prefix::Unqualified(_)
2119 | Prefix::Nested(_, _)
2120 | Prefix::TemplateParam(_)
2121 | Prefix::Decltype(_)
2122 | Prefix::DataMember(_, _) => None,
2123 }
2124 }
2125 }
2126
2127 define_handle! {
2128 /// A reference to a parsed `<prefix>` production.
2129 pub enum PrefixHandle {
2130 /// A handle to some `<prefix>` component that isn't by itself
2131 /// substitutable; instead, it's only substitutable *with* its parent
2132 /// component.
2133 extra NonSubstitution(NonSubstitution),
2134 }
2135 }
2136
2137 impl Parse for PrefixHandle {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(PrefixHandle, IndexStr<'b>)>2138 fn parse<'a, 'b>(
2139 ctx: &'a ParseContext,
2140 subs: &'a mut SubstitutionTable,
2141 input: IndexStr<'b>,
2142 ) -> Result<(PrefixHandle, IndexStr<'b>)> {
2143 try_begin_parse!("PrefixHandle", ctx, input);
2144
2145 #[inline]
2146 fn save(
2147 subs: &mut SubstitutionTable,
2148 prefix: Prefix,
2149 tail_tail: IndexStr<'_>,
2150 ) -> PrefixHandle {
2151 if let Some(b'E') = tail_tail.peek() {
2152 // An `E` means that we just finished parsing a `<nested-name>`
2153 // and this final set of prefixes isn't substitutable itself,
2154 // only as part of the whole `<nested-name>`. Since they are
2155 // effectively equivalent, it doesn't make sense to add entries
2156 // for both.
2157 let idx = subs.insert_non_substitution(Substitutable::Prefix(prefix));
2158 PrefixHandle::NonSubstitution(NonSubstitution(idx))
2159 } else {
2160 let idx = subs.insert(Substitutable::Prefix(prefix));
2161 PrefixHandle::BackReference(idx)
2162 }
2163 }
2164
2165 let mut tail = input;
2166 let mut current = None;
2167
2168 loop {
2169 try_begin_parse!("PrefixHandle iteration", ctx, tail);
2170
2171 match tail.peek() {
2172 Some(b'E') | None => if let Some(handle) = current {
2173 return Ok((handle, tail));
2174 } else {
2175 return Err(error::Error::UnexpectedEnd);
2176 },
2177 Some(b'S') => {
2178 // <prefix> ::= <substitution>
2179 let (sub, tail_tail) = Substitution::parse(ctx, subs, tail)?;
2180 current = Some(match sub {
2181 Substitution::WellKnown(component) => PrefixHandle::WellKnown(component),
2182 Substitution::BackReference(idx) => {
2183 // TODO: do we need to check that the idx actually points to
2184 // a Prefix?
2185 PrefixHandle::BackReference(idx)
2186 }
2187 });
2188 tail = tail_tail;
2189 }
2190 Some(b'T') => {
2191 // <prefix> ::= <template-param>
2192 let (param, tail_tail) = TemplateParam::parse(ctx, subs, tail)?;
2193 current = Some(save(subs, Prefix::TemplateParam(param), tail_tail));
2194 tail = tail_tail;
2195 }
2196 Some(b'D') => {
2197 // Either
2198 //
2199 // <prefix> ::= <decltype>
2200 //
2201 // or
2202 //
2203 // <prefix> ::= <unqualified-name> ::= <ctor-dtor-name>
2204 if let Ok((decltype, tail_tail)) = Decltype::parse(ctx, subs, tail) {
2205 current = Some(save(subs, Prefix::Decltype(decltype), tail_tail));
2206 tail = tail_tail;
2207 } else {
2208 let (name, tail_tail) = UnqualifiedName::parse(ctx, subs, tail)?;
2209 let prefix = match current {
2210 None => Prefix::Unqualified(name),
2211 Some(handle) => Prefix::Nested(handle, name),
2212 };
2213 current = Some(save(subs, prefix, tail_tail));
2214 tail = tail_tail;
2215 }
2216 }
2217 Some(b'I')
2218 if current.is_some() && current.as_ref().unwrap().is_template_prefix() =>
2219 {
2220 // <prefix> ::= <template-prefix> <template-args>
2221 let (args, tail_tail) = TemplateArgs::parse(ctx, subs, tail)?;
2222 let prefix = Prefix::Template(current.unwrap(), args);
2223 current = Some(save(subs, prefix, tail_tail));
2224 tail = tail_tail;
2225 }
2226 Some(c) if current.is_some() && SourceName::starts_with(c) => {
2227 // Either
2228 //
2229 // <prefix> ::= <unqualified-name> ::= <source-name>
2230 //
2231 // or
2232 //
2233 // <prefix> ::= <data-member-prefix> ::= <prefix> <source-name> M
2234 debug_assert!(SourceName::starts_with(c));
2235 debug_assert!(DataMemberPrefix::starts_with(c));
2236
2237 let (name, tail_tail) = SourceName::parse(ctx, subs, tail)?;
2238 if tail_tail.peek() == Some(b'M') {
2239 let prefix = Prefix::DataMember(current.unwrap(), DataMemberPrefix(name));
2240 current = Some(save(subs, prefix, tail_tail));
2241 tail = consume(b"M", tail_tail).unwrap();
2242 } else {
2243 let name = UnqualifiedName::Source(name);
2244 let prefix = match current {
2245 None => Prefix::Unqualified(name),
2246 Some(handle) => Prefix::Nested(handle, name),
2247 };
2248 current = Some(save(subs, prefix, tail_tail));
2249 tail = tail_tail;
2250 }
2251 }
2252 Some(c) if UnqualifiedName::starts_with(c, &tail) => {
2253 // <prefix> ::= <unqualified-name>
2254 let (name, tail_tail) = UnqualifiedName::parse(ctx, subs, tail)?;
2255 let prefix = match current {
2256 None => Prefix::Unqualified(name),
2257 Some(handle) => Prefix::Nested(handle, name),
2258 };
2259 current = Some(save(subs, prefix, tail_tail));
2260 tail = tail_tail;
2261 }
2262 Some(_) => if let Some(handle) = current {
2263 return Ok((handle, tail));
2264 } else if tail.is_empty() {
2265 return Err(error::Error::UnexpectedEnd);
2266 } else {
2267 return Err(error::Error::UnexpectedText);
2268 },
2269 }
2270 }
2271 }
2272 }
2273
2274 impl<'a> GetLeafName<'a> for Prefix {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>2275 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
2276 match *self {
2277 Prefix::Nested(ref prefix, ref name) => name.get_leaf_name(subs)
2278 .or_else(|| prefix.get_leaf_name(subs)),
2279 Prefix::Unqualified(ref name) => name.get_leaf_name(subs),
2280 Prefix::Template(ref prefix, _) => prefix.get_leaf_name(subs),
2281 Prefix::DataMember(_, ref name) => name.get_leaf_name(subs),
2282 Prefix::TemplateParam(_) | Prefix::Decltype(_) => None,
2283 }
2284 }
2285 }
2286
2287 impl GetTemplateArgs for PrefixHandle {
2288 // XXX: Not an impl GetTemplateArgs for PrefixHandle because the 'me
2289 // reference to self may not live long enough.
get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>2290 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
2291 match *self {
2292 PrefixHandle::BackReference(idx) => {
2293 if let Some(&Substitutable::Prefix(ref p)) = subs.get(idx) {
2294 p.get_template_args(subs)
2295 } else {
2296 None
2297 }
2298 }
2299 PrefixHandle::NonSubstitution(NonSubstitution(idx)) => {
2300 if let Some(&Substitutable::Prefix(ref p)) = subs.get_non_substitution(idx) {
2301 p.get_template_args(subs)
2302 } else {
2303 None
2304 }
2305 }
2306 _ => None,
2307 }
2308 }
2309 }
2310
2311 impl<'subs, W> Demangle<'subs, W> for Prefix
2312 where
2313 W: 'subs + DemangleWrite,
2314 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result2315 fn demangle<'prev, 'ctx>(
2316 &'subs self,
2317 ctx: &'ctx mut DemangleContext<'subs, W>,
2318 scope: Option<ArgScopeStack<'prev, 'subs>>,
2319 ) -> fmt::Result {
2320 let ctx = try_begin_demangle!(self, ctx, scope);
2321 if ctx.is_template_prefix {
2322 ctx.push_demangle_node(DemangleNodeType::TemplatePrefix);
2323 ctx.is_template_prefix = false;
2324 } else if ctx.is_template_prefix_in_nested_name {
2325 ctx.push_demangle_node(DemangleNodeType::NestedName);
2326 ctx.is_template_prefix_in_nested_name = false;
2327 } else {
2328 ctx.push_demangle_node(DemangleNodeType::Prefix);
2329 }
2330
2331 let ret = match *self {
2332 Prefix::Unqualified(ref unqualified) => unqualified.demangle(ctx, scope),
2333 Prefix::Nested(ref prefix, ref unqualified) => {
2334 prefix.demangle(ctx, scope)?;
2335 if unqualified.accepts_double_colon() {
2336 write!(ctx, "::")?;
2337 }
2338 unqualified.demangle(ctx, scope)
2339 }
2340 Prefix::Template(ref prefix, ref args) => {
2341 ctx.is_template_prefix = true;
2342 prefix.demangle(ctx, scope)?;
2343 ctx.is_template_prefix = false;
2344 args.demangle(ctx, scope)
2345 }
2346 Prefix::TemplateParam(ref param) => param.demangle(ctx, scope),
2347 Prefix::Decltype(ref dt) => dt.demangle(ctx, scope),
2348 Prefix::DataMember(ref prefix, ref member) => {
2349 prefix.demangle(ctx, scope)?;
2350 write!(ctx, "::")?;
2351 member.demangle(ctx, scope)
2352 }
2353 };
2354 ctx.pop_demangle_node();
2355 ret
2356 }
2357 }
2358
2359 impl IsCtorDtorConversion for Prefix {
is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool2360 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
2361 match *self {
2362 Prefix::Unqualified(ref unqualified) |
2363 Prefix::Nested(_, ref unqualified) => unqualified.is_ctor_dtor_conversion(subs),
2364 Prefix::Template(ref prefix, _) => prefix.is_ctor_dtor_conversion(subs),
2365 _ => false,
2366 }
2367 }
2368 }
2369
2370 impl IsCtorDtorConversion for PrefixHandle {
is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool2371 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
2372 match *self {
2373 PrefixHandle::BackReference(idx) => {
2374 if let Some(sub) = subs.get(idx) {
2375 sub.is_ctor_dtor_conversion(subs)
2376 } else {
2377 false
2378 }
2379 }
2380 PrefixHandle::NonSubstitution(NonSubstitution(idx)) => {
2381 if let Some(sub) = subs.get_non_substitution(idx) {
2382 sub.is_ctor_dtor_conversion(subs)
2383 } else {
2384 false
2385 }
2386 }
2387 PrefixHandle::WellKnown(_) => false,
2388 }
2389 }
2390 }
2391
2392 impl PrefixHandle {
2393 // Is this <prefix> also a valid <template-prefix> production? Not to be
2394 // confused with the `GetTemplateArgs` trait.
is_template_prefix(&self) -> bool2395 fn is_template_prefix(&self) -> bool {
2396 match *self {
2397 PrefixHandle::BackReference(_) |
2398 PrefixHandle::WellKnown(_) => true,
2399 PrefixHandle::NonSubstitution(_) => false,
2400 }
2401 }
2402 }
2403
2404 /// The `<unqualified-name>` production.
2405 ///
2406 /// ```text
2407 /// <unqualified-name> ::= <operator-name>
2408 /// ::= <ctor-dtor-name>
2409 /// ::= <source-name>
2410 /// ::= <local-source-name>
2411 /// ::= <unnamed-type-name>
2412 /// ::= <abi-tag>
2413 /// ::= <closure-type-name>
2414 ///
2415 /// # I think this is from an older version of the standard. It isn't in the
2416 /// # current version, but all the other demanglers support it, so we will too.
2417 /// <local-source-name> ::= L <source-name> [<discriminator>]
2418 /// ```
2419 #[derive(Clone, Debug, PartialEq, Eq)]
2420 pub enum UnqualifiedName {
2421 /// An operator name.
2422 Operator(OperatorName),
2423 /// A constructor or destructor name.
2424 CtorDtor(CtorDtorName),
2425 /// A source name.
2426 Source(SourceName),
2427 /// A local source name.
2428 LocalSourceName(SourceName, Option<Discriminator>),
2429 /// A generated name for an unnamed type.
2430 UnnamedType(UnnamedTypeName),
2431 /// An ABI tag.
2432 ABITag(TaggedName),
2433 /// A closure type name
2434 ClosureType(ClosureTypeName),
2435 }
2436
2437 impl Parse for UnqualifiedName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(UnqualifiedName, IndexStr<'b>)>2438 fn parse<'a, 'b>(
2439 ctx: &'a ParseContext,
2440 subs: &'a mut SubstitutionTable,
2441 input: IndexStr<'b>,
2442 ) -> Result<(UnqualifiedName, IndexStr<'b>)> {
2443 try_begin_parse!("UnqualifiedName", ctx, input);
2444
2445 if let Ok((op, tail)) = OperatorName::parse(ctx, subs, input) {
2446 return Ok((UnqualifiedName::Operator(op), tail));
2447 }
2448
2449 if let Ok((ctor_dtor, tail)) = CtorDtorName::parse(ctx, subs, input) {
2450 return Ok((UnqualifiedName::CtorDtor(ctor_dtor), tail));
2451 }
2452
2453 if let Ok(tail) = consume(b"L", input) {
2454 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
2455 let (discr, tail) = if let Ok((d, t)) = Discriminator::parse(ctx, subs, tail) {
2456 (Some(d), t)
2457 } else {
2458 (None, tail)
2459 };
2460 return Ok((UnqualifiedName::LocalSourceName(name, discr), tail));
2461 }
2462
2463 if let Ok((source, tail)) = SourceName::parse(ctx, subs, input) {
2464 return Ok((UnqualifiedName::Source(source), tail));
2465 }
2466
2467 if let Ok((tagged, tail)) = TaggedName::parse(ctx, subs, input) {
2468 return Ok((UnqualifiedName::ABITag(tagged), tail));
2469 }
2470
2471 if let Ok((closure, tail)) = ClosureTypeName::parse(ctx, subs, input) {
2472 return Ok((UnqualifiedName::ClosureType(closure), tail));
2473 }
2474
2475 UnnamedTypeName::parse(ctx, subs, input).map(|(unnamed, tail)| {
2476 (UnqualifiedName::UnnamedType(unnamed), tail)
2477 })
2478 }
2479 }
2480
2481 impl<'subs, W> Demangle<'subs, W> for UnqualifiedName
2482 where
2483 W: 'subs + DemangleWrite,
2484 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result2485 fn demangle<'prev, 'ctx>(
2486 &'subs self,
2487 ctx: &'ctx mut DemangleContext<'subs, W>,
2488 scope: Option<ArgScopeStack<'prev, 'subs>>,
2489 ) -> fmt::Result {
2490 let ctx = try_begin_demangle!(self, ctx, scope);
2491
2492 ctx.push_demangle_node(DemangleNodeType::UnqualifiedName);
2493 let ret = match *self {
2494 UnqualifiedName::Operator(ref op_name) => {
2495 write!(ctx, "operator")?;
2496 op_name.demangle(ctx, scope)
2497 }
2498 UnqualifiedName::CtorDtor(ref ctor_dtor) => ctor_dtor.demangle(ctx, scope),
2499 UnqualifiedName::Source(ref name) | UnqualifiedName::LocalSourceName(ref name, ..) => {
2500 name.demangle(ctx, scope)
2501 }
2502 UnqualifiedName::UnnamedType(ref unnamed) => unnamed.demangle(ctx, scope),
2503 UnqualifiedName::ABITag(ref tagged) => tagged.demangle(ctx, scope),
2504 UnqualifiedName::ClosureType(ref closure) => closure.demangle(ctx, scope),
2505 };
2506 ctx.pop_demangle_node();
2507 ret
2508 }
2509 }
2510
2511 impl<'a> GetLeafName<'a> for UnqualifiedName {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>2512 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
2513 match *self {
2514 UnqualifiedName::ABITag(_)
2515 | UnqualifiedName::Operator(_)
2516 | UnqualifiedName::CtorDtor(_) => None,
2517 UnqualifiedName::UnnamedType(ref name) => {
2518 Some(LeafName::UnnamedType(name))
2519 },
2520 UnqualifiedName::ClosureType(ref closure) => closure.get_leaf_name(subs),
2521 UnqualifiedName::Source(ref name) | UnqualifiedName::LocalSourceName(ref name, _) => {
2522 Some(LeafName::SourceName(name))
2523 }
2524 }
2525 }
2526 }
2527
2528 impl IsCtorDtorConversion for UnqualifiedName {
is_ctor_dtor_conversion(&self, _: &SubstitutionTable) -> bool2529 fn is_ctor_dtor_conversion(&self, _: &SubstitutionTable) -> bool {
2530 match *self {
2531 UnqualifiedName::CtorDtor(_) |
2532 UnqualifiedName::Operator(OperatorName::Conversion(_)) => true,
2533 UnqualifiedName::Operator(_) |
2534 UnqualifiedName::Source(_) |
2535 UnqualifiedName::LocalSourceName(..) |
2536 UnqualifiedName::UnnamedType(_) |
2537 UnqualifiedName::ClosureType(_) |
2538 UnqualifiedName::ABITag(_) => false,
2539 }
2540 }
2541 }
2542
2543 impl UnqualifiedName {
2544 #[inline]
starts_with(byte: u8, input: &IndexStr) -> bool2545 fn starts_with(byte: u8, input: &IndexStr) -> bool {
2546 byte == b'L' || OperatorName::starts_with(byte) || CtorDtorName::starts_with(byte)
2547 || SourceName::starts_with(byte) || UnnamedTypeName::starts_with(byte)
2548 || TaggedName::starts_with(byte) || ClosureTypeName::starts_with(byte, input)
2549 }
2550
accepts_double_colon(&self) -> bool2551 fn accepts_double_colon(&self) -> bool {
2552 match *self {
2553 UnqualifiedName::Operator(_)
2554 | UnqualifiedName::CtorDtor(_)
2555 | UnqualifiedName::Source(_)
2556 | UnqualifiedName::LocalSourceName(..)
2557 | UnqualifiedName::UnnamedType(_)
2558 | UnqualifiedName::ClosureType(_) => true,
2559 UnqualifiedName::ABITag(_) => false,
2560 }
2561 }
2562 }
2563
2564 /// The `<source-name>` non-terminal.
2565 ///
2566 /// ```text
2567 /// <source-name> ::= <positive length number> <identifier>
2568 /// ```
2569 #[derive(Clone, Debug, PartialEq, Eq)]
2570 pub struct SourceName(Identifier);
2571
2572 impl Parse for SourceName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(SourceName, IndexStr<'b>)>2573 fn parse<'a, 'b>(
2574 ctx: &'a ParseContext,
2575 subs: &'a mut SubstitutionTable,
2576 input: IndexStr<'b>,
2577 ) -> Result<(SourceName, IndexStr<'b>)> {
2578 try_begin_parse!("SourceName", ctx, input);
2579
2580 let (source_name_len, input) = parse_number(10, false, input)?;
2581 debug_assert!(source_name_len >= 0);
2582 if source_name_len == 0 {
2583 return Err(error::Error::UnexpectedText);
2584 }
2585
2586 let (head, tail) = match input.try_split_at(source_name_len as _) {
2587 Some((head, tail)) => (head, tail),
2588 None => return Err(error::Error::UnexpectedEnd),
2589 };
2590
2591 let (identifier, empty) = Identifier::parse(ctx, subs, head)?;
2592 if !empty.is_empty() {
2593 return Err(error::Error::UnexpectedText);
2594 }
2595
2596 let source_name = SourceName(identifier);
2597 Ok((source_name, tail))
2598 }
2599 }
2600
2601 impl<'subs> ArgScope<'subs, 'subs> for SourceName {
leaf_name(&'subs self) -> Result<LeafName<'subs>>2602 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
2603 Ok(LeafName::SourceName(self))
2604 }
2605
get_template_arg(&'subs self, _: usize) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)>2606 fn get_template_arg(&'subs self, _: usize) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
2607 Err(error::Error::BadTemplateArgReference)
2608 }
2609
get_function_arg(&'subs self, _: usize) -> Result<&'subs Type>2610 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
2611 Err(error::Error::BadFunctionArgReference)
2612 }
2613 }
2614
2615 impl SourceName {
2616 #[inline]
starts_with(byte: u8) -> bool2617 fn starts_with(byte: u8) -> bool {
2618 byte == b'0' || (b'0' <= byte && byte <= b'9')
2619 }
2620 }
2621
2622 impl<'subs, W> Demangle<'subs, W> for SourceName
2623 where
2624 W: 'subs + DemangleWrite,
2625 {
2626 #[inline]
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result2627 fn demangle<'prev, 'ctx>(
2628 &'subs self,
2629 ctx: &'ctx mut DemangleContext<'subs, W>,
2630 scope: Option<ArgScopeStack<'prev, 'subs>>,
2631 ) -> fmt::Result {
2632 let ctx = try_begin_demangle!(self, ctx, scope);
2633
2634 self.0.demangle(ctx, scope)
2635 }
2636 }
2637
2638 /// The `<tagged-name>` non-terminal.
2639 ///
2640 /// ```text
2641 /// <tagged-name> ::= <name> B <source-name>
2642 /// ```
2643 #[derive(Clone, Debug, PartialEq, Eq)]
2644 pub struct TaggedName(SourceName);
2645
2646 impl Parse for TaggedName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(TaggedName, IndexStr<'b>)>2647 fn parse<'a, 'b>(
2648 ctx: &'a ParseContext,
2649 subs: &'a mut SubstitutionTable,
2650 input: IndexStr<'b>,
2651 ) -> Result<(TaggedName, IndexStr<'b>)> {
2652 try_begin_parse!("TaggedName", ctx, input);
2653
2654 let tail = consume(b"B", input)?;
2655 let (source_name, tail) = SourceName::parse(ctx, subs, tail)?;
2656 Ok((TaggedName(source_name), tail))
2657 }
2658 }
2659
2660 impl<'subs, W> Demangle<'subs, W> for TaggedName
2661 where
2662 W: 'subs + DemangleWrite,
2663 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result2664 fn demangle<'prev, 'ctx>(
2665 &'subs self,
2666 ctx: &'ctx mut DemangleContext<'subs, W>,
2667 scope: Option<ArgScopeStack<'prev, 'subs>>,
2668 ) -> fmt::Result {
2669 let ctx = try_begin_demangle!(self, ctx, scope);
2670
2671 write!(ctx, "[abi:")?;
2672 self.0.demangle(ctx, scope)?;
2673 write!(ctx, "]")
2674 }
2675 }
2676
2677 impl TaggedName {
2678 #[inline]
starts_with(byte: u8) -> bool2679 fn starts_with(byte: u8) -> bool {
2680 byte == b'B'
2681 }
2682 }
2683
2684 /// The `<identifier>` pseudo-terminal.
2685 ///
2686 /// ```text
2687 /// <identifier> ::= <unqualified source code identifier>
2688 /// ```
2689 ///
2690 /// > `<identifier>` is a pseudo-terminal representing the characters in the
2691 /// > unqualified identifier for the entity in the source code. This ABI does not
2692 /// > yet specify a mangling for identifiers containing characters outside of
2693 /// > `_A-Za-z0-9.`.
2694 ///
2695 /// Mangled symbols' identifiers also have `$` characters in the wild.
2696 #[derive(Clone, Debug, PartialEq, Eq)]
2697 pub struct Identifier {
2698 start: usize,
2699 end: usize,
2700 }
2701
2702 impl Parse for Identifier {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Identifier, IndexStr<'b>)>2703 fn parse<'a, 'b>(
2704 ctx: &'a ParseContext,
2705 _subs: &'a mut SubstitutionTable,
2706 input: IndexStr<'b>,
2707 ) -> Result<(Identifier, IndexStr<'b>)> {
2708 try_begin_parse!("Identifier", ctx, input);
2709
2710 if input.is_empty() {
2711 return Err(error::Error::UnexpectedEnd);
2712 }
2713
2714 let end = input
2715 .as_ref()
2716 .iter()
2717 .map(|&c| c as char)
2718 .take_while(|&c| c == '$' || c == '_' || c == '.' || c.is_digit(36))
2719 .count();
2720
2721 if end == 0 {
2722 return Err(error::Error::UnexpectedText);
2723 }
2724
2725 let tail = input.range_from(end..);
2726
2727 let identifier = Identifier {
2728 start: input.index(),
2729 end: tail.index(),
2730 };
2731
2732 Ok((identifier, tail))
2733 }
2734 }
2735
2736 impl<'subs, W> Demangle<'subs, W> for Identifier
2737 where
2738 W: 'subs + DemangleWrite,
2739 {
2740 #[inline]
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result2741 fn demangle<'prev, 'ctx>(
2742 &'subs self,
2743 ctx: &'ctx mut DemangleContext<'subs, W>,
2744 scope: Option<ArgScopeStack<'prev, 'subs>>,
2745 ) -> fmt::Result {
2746 let ctx = try_begin_demangle!(self, ctx, scope);
2747
2748 let ident = &ctx.input[self.start..self.end];
2749
2750 // Handle GCC's anonymous namespace mangling.
2751 let anon_namespace_prefix = b"_GLOBAL_";
2752 if ident.starts_with(anon_namespace_prefix)
2753 && ident.len() >= anon_namespace_prefix.len() + 2
2754 {
2755 let first = ident[anon_namespace_prefix.len()];
2756 let second = ident[anon_namespace_prefix.len() + 1];
2757
2758 match (first, second) {
2759 (b'.', b'N') | (b'_', b'N') | (b'$', b'N') => {
2760 write!(ctx, "(anonymous namespace)")?;
2761 return Ok(());
2762 }
2763 _ => {
2764 // Fall through.
2765 }
2766 }
2767 }
2768
2769 let source_name = String::from_utf8_lossy(ident);
2770 ctx.set_source_name(self.start, self.end);
2771 write!(ctx, "{}", source_name)?;
2772 Ok(())
2773 }
2774 }
2775
2776 /// The `<clone-type-identifier>` pseudo-terminal.
2777 ///
2778 /// ```text
2779 /// <clone-type-identifier> ::= <unqualified source code identifier>
2780 /// ```
2781 #[derive(Clone, Debug, PartialEq, Eq)]
2782 pub struct CloneTypeIdentifier {
2783 start: usize,
2784 end: usize,
2785 }
2786
2787 impl Parse for CloneTypeIdentifier {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(CloneTypeIdentifier, IndexStr<'b>)>2788 fn parse<'a, 'b>(
2789 ctx: &'a ParseContext,
2790 _subs: &'a mut SubstitutionTable,
2791 input: IndexStr<'b>,
2792 ) -> Result<(CloneTypeIdentifier, IndexStr<'b>)> {
2793 try_begin_parse!("CloneTypeIdentifier", ctx, input);
2794
2795 if input.is_empty() {
2796 return Err(error::Error::UnexpectedEnd);
2797 }
2798
2799 let end = input
2800 .as_ref()
2801 .iter()
2802 .map(|&c| c as char)
2803 .take_while(|&c| c == '$' || c == '_' || c.is_digit(36))
2804 .count();
2805
2806 if end == 0 {
2807 return Err(error::Error::UnexpectedText);
2808 }
2809
2810 let tail = input.range_from(end..);
2811
2812 let identifier = CloneTypeIdentifier {
2813 start: input.index(),
2814 end: tail.index(),
2815 };
2816
2817 Ok((identifier, tail))
2818 }
2819 }
2820
2821 impl<'subs, W> Demangle<'subs, W> for CloneTypeIdentifier
2822 where
2823 W: 'subs + DemangleWrite,
2824 {
2825 #[inline]
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result2826 fn demangle<'prev, 'ctx>(
2827 &'subs self,
2828 ctx: &'ctx mut DemangleContext<'subs, W>,
2829 scope: Option<ArgScopeStack<'prev, 'subs>>,
2830 ) -> fmt::Result {
2831 let ctx = try_begin_demangle!(self, ctx, scope);
2832
2833 let ident = &ctx.input[self.start..self.end];
2834
2835 let source_name = String::from_utf8_lossy(ident);
2836 ctx.set_source_name(self.start, self.end);
2837 write!(ctx, " .{}", source_name)?;
2838 Ok(())
2839 }
2840 }
2841
2842 /// The `<number>` production.
2843 ///
2844 /// ```text
2845 /// <number> ::= [n] <non-negative decimal integer>
2846 /// ```
2847 type Number = isize;
2848
2849 impl Parse for Number {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(isize, IndexStr<'b>)>2850 fn parse<'a, 'b>(
2851 ctx: &'a ParseContext,
2852 _subs: &'a mut SubstitutionTable,
2853 input: IndexStr<'b>,
2854 ) -> Result<(isize, IndexStr<'b>)> {
2855 try_begin_parse!("Number", ctx, input);
2856 parse_number(10, true, input)
2857 }
2858 }
2859
2860 /// A <seq-id> production encoding a base-36 positive number.
2861 ///
2862 /// ```text
2863 /// <seq-id> ::= <0-9A-Z>+
2864 /// ```
2865 #[derive(Clone, Debug, PartialEq, Eq)]
2866 pub struct SeqId(usize);
2867
2868 impl Parse for SeqId {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(SeqId, IndexStr<'b>)>2869 fn parse<'a, 'b>(
2870 ctx: &'a ParseContext,
2871 _subs: &'a mut SubstitutionTable,
2872 input: IndexStr<'b>,
2873 ) -> Result<(SeqId, IndexStr<'b>)> {
2874 try_begin_parse!("SeqId", ctx, input);
2875
2876 parse_number(36, false, input).map(|(num, tail)| (SeqId(num as _), tail))
2877 }
2878 }
2879
2880 /// The `<operator-name>` production.
2881 ///
2882 /// ```text
2883 /// <operator-name> ::= <simple-operator-name>
2884 /// ::= cv <type> # (cast)
2885 /// ::= li <source-name> # operator ""
2886 /// ::= v <digit> <source-name> # vendor extended operator
2887 /// ```
2888 #[derive(Clone, Debug, PartialEq, Eq)]
2889 pub enum OperatorName {
2890 /// A simple operator name.
2891 Simple(SimpleOperatorName),
2892
2893 /// A type cast.
2894 Cast(TypeHandle),
2895
2896 /// A type conversion.
2897 Conversion(TypeHandle),
2898
2899 /// Operator literal, ie `operator ""`.
2900 Literal(SourceName),
2901
2902 /// A non-standard, vendor extension operator.
2903 VendorExtension(u8, SourceName),
2904 }
2905
2906 impl OperatorName {
starts_with(byte: u8) -> bool2907 fn starts_with(byte: u8) -> bool {
2908 byte == b'c' || byte == b'l' || byte == b'v' || SimpleOperatorName::starts_with(byte)
2909 }
2910
arity(&self) -> u82911 fn arity(&self) -> u8 {
2912 match self {
2913 &OperatorName::Cast(_) |
2914 &OperatorName::Conversion(_) |
2915 &OperatorName::Literal(_) => 1,
2916 &OperatorName::Simple(ref s) => s.arity(),
2917 &OperatorName::VendorExtension(arity, _) => arity,
2918 }
2919 }
2920
parse_from_expr<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b> ) -> Result<(Expression, IndexStr<'b>)>2921 fn parse_from_expr<'a, 'b>(
2922 ctx: &'a ParseContext,
2923 subs: &'a mut SubstitutionTable,
2924 input: IndexStr<'b>
2925 ) -> Result<(Expression, IndexStr<'b>)> {
2926 let (operator, tail) = OperatorName::parse_internal(ctx, subs, input, true)?;
2927
2928 let arity = operator.arity();
2929 if arity == 1 {
2930 let (first, tail) = Expression::parse(ctx, subs, tail)?;
2931 let expr = Expression::Unary(operator, Box::new(first));
2932 Ok((expr, tail))
2933 } else if arity == 2 {
2934 let (first, tail) = Expression::parse(ctx, subs, tail)?;
2935 let (second, tail) = Expression::parse(ctx, subs, tail)?;
2936 let expr = Expression::Binary(operator, Box::new(first), Box::new(second));
2937 Ok((expr, tail))
2938 } else if arity == 3 {
2939 let (first, tail) = Expression::parse(ctx, subs, tail)?;
2940 let (second, tail) = Expression::parse(ctx, subs, tail)?;
2941 let (third, tail) = Expression::parse(ctx, subs, tail)?;
2942 let expr =
2943 Expression::Ternary(operator, Box::new(first), Box::new(second), Box::new(third));
2944 Ok((expr, tail))
2945 } else {
2946 Err(error::Error::UnexpectedText)
2947 }
2948 }
2949
parse_internal<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, from_expr: bool, ) -> Result<(OperatorName, IndexStr<'b>)>2950 fn parse_internal<'a, 'b>(
2951 ctx: &'a ParseContext,
2952 subs: &'a mut SubstitutionTable,
2953 input: IndexStr<'b>,
2954 from_expr: bool,
2955 ) -> Result<(OperatorName, IndexStr<'b>)> {
2956 try_begin_parse!("OperatorName", ctx, input);
2957
2958 if let Ok((simple, tail)) = SimpleOperatorName::parse(ctx, subs, input) {
2959 return Ok((OperatorName::Simple(simple), tail));
2960 }
2961
2962 if let Ok(tail) = consume(b"cv", input) {
2963 // If we came through the expression path, we're a cast. If not,
2964 // we're a conversion.
2965 let previously_in_conversion = ctx.set_in_conversion(!from_expr);
2966 let parse_result = TypeHandle::parse(ctx, subs, tail);
2967 ctx.set_in_conversion(previously_in_conversion);
2968 let (ty, tail) = parse_result?;
2969 if from_expr {
2970 return Ok((OperatorName::Cast(ty), tail));
2971 } else {
2972 return Ok((OperatorName::Conversion(ty), tail));
2973 }
2974 }
2975
2976 if let Ok(tail) = consume(b"li", input) {
2977 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
2978 return Ok((OperatorName::Literal(name), tail));
2979 }
2980
2981 let tail = consume(b"v", input)?;
2982 let (arity, tail) = match tail.peek() {
2983 Some(c) if b'0' <= c && c <= b'9' => (c - b'0', tail.range_from(1..)),
2984 None => return Err(error::Error::UnexpectedEnd),
2985 _ => return Err(error::Error::UnexpectedText),
2986 };
2987 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
2988 Ok((OperatorName::VendorExtension(arity, name), tail))
2989 }
2990 }
2991
2992 impl Parse for OperatorName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(OperatorName, IndexStr<'b>)>2993 fn parse<'a, 'b>(
2994 ctx: &'a ParseContext,
2995 subs: &'a mut SubstitutionTable,
2996 input: IndexStr<'b>,
2997 ) -> Result<(OperatorName, IndexStr<'b>)> {
2998 OperatorName::parse_internal(ctx, subs, input, false)
2999 }
3000 }
3001
3002 impl<'subs, W> Demangle<'subs, W> for OperatorName
3003 where
3004 W: 'subs + DemangleWrite,
3005 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result3006 fn demangle<'prev, 'ctx>(
3007 &'subs self,
3008 ctx: &'ctx mut DemangleContext<'subs, W>,
3009 scope: Option<ArgScopeStack<'prev, 'subs>>,
3010 ) -> fmt::Result {
3011 let ctx = try_begin_demangle!(self, ctx, scope);
3012
3013 match *self {
3014 OperatorName::Simple(ref simple) => {
3015 match *simple {
3016 SimpleOperatorName::New
3017 | SimpleOperatorName::NewArray
3018 | SimpleOperatorName::Delete
3019 | SimpleOperatorName::DeleteArray => {
3020 ctx.ensure_space()?;
3021 }
3022 _ => {}
3023 }
3024 simple.demangle(ctx, scope)
3025 }
3026 OperatorName::Cast(ref ty) |
3027 OperatorName::Conversion(ref ty) => {
3028 ctx.ensure_space()?;
3029
3030 // Cast operators can refer to template arguments before they
3031 // actually appear in the AST, so we go traverse down the tree
3032 // and fetch them if they exist.
3033 let scope = ty.get_template_args(ctx.subs)
3034 .map_or(scope, |args| scope.push(args));
3035
3036 ty.demangle(ctx, scope)?;
3037 Ok(())
3038 }
3039 OperatorName::Literal(ref name) => {
3040 name.demangle(ctx, scope)?;
3041 write!(ctx, "::operator \"\"")?;
3042 Ok(())
3043 }
3044 OperatorName::VendorExtension(arity, ref name) => {
3045 // TODO: no idea how this should be demangled...
3046 name.demangle(ctx, scope)?;
3047 write!(ctx, "::operator {}", arity)?;
3048 Ok(())
3049 }
3050 }
3051 }
3052 }
3053
3054 define_vocabulary! {
3055 /// The `<simple-operator-name>` production.
3056 #[derive(Clone, Debug, PartialEq, Eq)]
3057 pub enum SimpleOperatorName {
3058 New (b"nw", "new", 3),
3059 NewArray (b"na", "new[]", 3),
3060 Delete (b"dl", "delete", 1),
3061 DeleteArray (b"da", "delete[]", 1),
3062 UnaryPlus (b"ps", "+", 1),
3063 Neg (b"ng", "-", 1),
3064 AddressOf (b"ad", "&", 1),
3065 Deref (b"de", "*", 1),
3066 BitNot (b"co", "~", 1),
3067 Add (b"pl", "+", 2),
3068 Sub (b"mi", "-", 2),
3069 Mul (b"ml", "*", 2),
3070 Div (b"dv", "/", 2),
3071 Rem (b"rm", "%", 2),
3072 BitAnd (b"an", "&", 2),
3073 BitOr (b"or", "|", 2),
3074 BitXor (b"eo", "^", 2),
3075 Assign (b"aS", "=", 2),
3076 AddAssign (b"pL", "+=", 2),
3077 SubAssign (b"mI", "-=", 2),
3078 MulAssign (b"mL", "*=", 2),
3079 DivAssign (b"dV", "/=", 2),
3080 RemAssign (b"rM", "%=", 2),
3081 BitAndAssign (b"aN", "&=", 2),
3082 BitOrAssign (b"oR", "|=", 2),
3083 BitXorAssign (b"eO", "^=", 2),
3084 Shl (b"ls", "<<", 2),
3085 Shr (b"rs", ">>", 2),
3086 ShlAssign (b"lS", "<<=", 2),
3087 ShrAssign (b"rS", ">>=", 2),
3088 Eq (b"eq", "==", 2),
3089 Ne (b"ne", "!=", 2),
3090 Less (b"lt", "<", 2),
3091 Greater (b"gt", ">", 2),
3092 LessEq (b"le", "<=", 2),
3093 GreaterEq (b"ge", ">=", 2),
3094 Not (b"nt", "!", 1),
3095 LogicalAnd (b"aa", "&&", 2),
3096 LogicalOr (b"oo", "||", 2),
3097 PostInc (b"pp", "++", 1), // (postfix in <expression> context)
3098 PostDec (b"mm", "--", 1), // (postfix in <expression> context)
3099 Comma (b"cm", ",", 2),
3100 DerefMemberPtr (b"pm", "->*", 2),
3101 DerefMember (b"pt", "->", 2),
3102 Call (b"cl", "()", 2),
3103 Index (b"ix", "[]", 2),
3104 Question (b"qu", "?:", 3),
3105 Spaceship (b"ss", "<=>", 2)
3106 }
3107
3108 impl SimpleOperatorName {
3109 // Automatically implemented by define_vocabulary!
3110 fn arity(&self) -> u8;
3111 }
3112 }
3113
3114 /// The `<call-offset>` production.
3115 ///
3116 /// ```text
3117 /// <call-offset> ::= h <nv-offset> _
3118 /// ::= v <v-offset> _
3119 /// ```
3120 #[derive(Clone, Debug, PartialEq, Eq)]
3121 pub enum CallOffset {
3122 /// A non-virtual offset.
3123 NonVirtual(NvOffset),
3124 /// A virtual offset.
3125 Virtual(VOffset),
3126 }
3127
3128 impl Parse for CallOffset {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(CallOffset, IndexStr<'b>)>3129 fn parse<'a, 'b>(
3130 ctx: &'a ParseContext,
3131 subs: &'a mut SubstitutionTable,
3132 input: IndexStr<'b>,
3133 ) -> Result<(CallOffset, IndexStr<'b>)> {
3134 try_begin_parse!("CallOffset", ctx, input);
3135
3136 if input.is_empty() {
3137 return Err(error::Error::UnexpectedEnd);
3138 }
3139
3140 if let Ok(tail) = consume(b"h", input) {
3141 let (offset, tail) = NvOffset::parse(ctx, subs, tail)?;
3142 let tail = consume(b"_", tail)?;
3143 return Ok((CallOffset::NonVirtual(offset), tail));
3144 }
3145
3146 if let Ok(tail) = consume(b"v", input) {
3147 let (offset, tail) = VOffset::parse(ctx, subs, tail)?;
3148 let tail = consume(b"_", tail)?;
3149 return Ok((CallOffset::Virtual(offset), tail));
3150 }
3151
3152 Err(error::Error::UnexpectedText)
3153 }
3154 }
3155
3156 impl<'subs, W> Demangle<'subs, W> for CallOffset
3157 where
3158 W: 'subs + DemangleWrite,
3159 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result3160 fn demangle<'prev, 'ctx>(
3161 &'subs self,
3162 ctx: &'ctx mut DemangleContext<'subs, W>,
3163 scope: Option<ArgScopeStack<'prev, 'subs>>,
3164 ) -> fmt::Result {
3165 let ctx = try_begin_demangle!(self, ctx, scope);
3166
3167 match *self {
3168 CallOffset::NonVirtual(NvOffset(offset)) => {
3169 write!(ctx, "{{offset({})}}", offset)?;
3170 }
3171 CallOffset::Virtual(VOffset(vbase, vcall)) => {
3172 write!(ctx, "{{virtual offset({}, {})}}", vbase, vcall)?;
3173 }
3174 }
3175 Ok(())
3176 }
3177 }
3178
3179 /// A non-virtual offset, as described by the <nv-offset> production.
3180 ///
3181 /// ```text
3182 /// <nv-offset> ::= <offset number>
3183 /// ```
3184 #[derive(Clone, Debug, PartialEq, Eq)]
3185 pub struct NvOffset(isize);
3186
3187 impl Parse for NvOffset {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(NvOffset, IndexStr<'b>)>3188 fn parse<'a, 'b>(
3189 ctx: &'a ParseContext,
3190 subs: &'a mut SubstitutionTable,
3191 input: IndexStr<'b>,
3192 ) -> Result<(NvOffset, IndexStr<'b>)> {
3193 try_begin_parse!("NvOffset", ctx, input);
3194
3195 Number::parse(ctx, subs, input).map(|(num, tail)| (NvOffset(num), tail))
3196 }
3197 }
3198
3199 /// A virtual offset, as described by the <v-offset> production.
3200 ///
3201 /// ```text
3202 /// <v-offset> ::= <offset number> _ <virtual offset number>
3203 /// ```
3204 #[derive(Clone, Debug, PartialEq, Eq)]
3205 pub struct VOffset(isize, isize);
3206
3207 impl Parse for VOffset {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(VOffset, IndexStr<'b>)>3208 fn parse<'a, 'b>(
3209 ctx: &'a ParseContext,
3210 subs: &'a mut SubstitutionTable,
3211 input: IndexStr<'b>,
3212 ) -> Result<(VOffset, IndexStr<'b>)> {
3213 try_begin_parse!("VOffset", ctx, input);
3214
3215 let (offset, tail) = Number::parse(ctx, subs, input)?;
3216 let tail = consume(b"_", tail)?;
3217 let (virtual_offset, tail) = Number::parse(ctx, subs, tail)?;
3218 Ok((VOffset(offset, virtual_offset), tail))
3219 }
3220 }
3221
3222 /// The `<ctor-dtor-name>` production.
3223 ///
3224 /// ```text
3225 /// <ctor-dtor-name> ::= C1 # complete object constructor
3226 /// ::= C2 # base object constructor
3227 /// ::= C3 # complete object allocating constructor
3228 /// ::= D0 # deleting destructor
3229 /// ::= D1 # complete object destructor
3230 /// ::= D2 # base object destructor
3231 /// ```
3232 ///
3233 /// GCC also emits a C4 constructor under some conditions when building
3234 /// an optimized binary. GCC's source says:
3235 ///
3236 /// ```
3237 /// /* This is the old-style "[unified]" constructor.
3238 /// In some cases, we may emit this function and call
3239 /// it from the clones in order to share code and save space. */
3240 /// ```
3241 ///
3242 /// Based on the GCC source we'll call this the "maybe in-charge constructor".
3243 /// Similarly, there is a D4 destructor, the "maybe in-charge destructor".
3244 #[derive(Clone, Debug, PartialEq, Eq)]
3245 pub enum CtorDtorName {
3246 /// "C1", the "complete object constructor"
3247 CompleteConstructor(Option<TypeHandle>),
3248 /// "C2", the "base object constructor"
3249 BaseConstructor(Option<TypeHandle>),
3250 /// "C3", the "complete object allocating constructor"
3251 CompleteAllocatingConstructor(Option<TypeHandle>),
3252 /// "C4", the "maybe in-charge constructor"
3253 MaybeInChargeConstructor(Option<TypeHandle>),
3254 /// "D0", the "deleting destructor"
3255 DeletingDestructor,
3256 /// "D1", the "complete object destructor"
3257 CompleteDestructor,
3258 /// "D2", the "base object destructor"
3259 BaseDestructor,
3260 /// "D4", the "maybe in-charge destructor"
3261 MaybeInChargeDestructor,
3262 }
3263
3264 impl CtorDtorName {
inheriting_mut(&mut self) -> &mut Option<TypeHandle>3265 fn inheriting_mut(&mut self) -> &mut Option<TypeHandle> {
3266 match self {
3267 CtorDtorName::CompleteConstructor(ref mut inheriting)
3268 | CtorDtorName::BaseConstructor(ref mut inheriting)
3269 | CtorDtorName::CompleteAllocatingConstructor(ref mut inheriting)
3270 | CtorDtorName::MaybeInChargeConstructor(ref mut inheriting) => inheriting,
3271 CtorDtorName::DeletingDestructor
3272 | CtorDtorName::CompleteDestructor
3273 | CtorDtorName::BaseDestructor
3274 | CtorDtorName::MaybeInChargeDestructor => unreachable!(),
3275 }
3276 }
3277 }
3278
3279 impl Parse for CtorDtorName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(CtorDtorName, IndexStr<'b>)>3280 fn parse<'a, 'b>(
3281 ctx: &'a ParseContext,
3282 subs: &'a mut SubstitutionTable,
3283 input: IndexStr<'b>,
3284 ) -> Result<(CtorDtorName, IndexStr<'b>)> {
3285 try_begin_parse!(stringify!(CtorDtorName), ctx, input);
3286
3287 match input.peek() {
3288 Some(b'C') => {
3289 let mut tail = consume(b"C", input)?;
3290 let inheriting = match tail.peek() {
3291 Some(b'I') => {
3292 tail = consume(b"I", tail)?;
3293 true
3294 }
3295 _ => false,
3296 };
3297
3298 let mut ctor_type: CtorDtorName = match tail
3299 .try_split_at(1)
3300 .as_ref()
3301 .map(|&(ref h, t)| (h.as_ref(), t))
3302 {
3303 None => Err(error::Error::UnexpectedEnd),
3304 Some((b"1", t)) => {
3305 tail = t;
3306 Ok(CtorDtorName::CompleteConstructor(None))
3307 },
3308 Some((b"2", t)) => {
3309 tail = t;
3310 Ok(CtorDtorName::BaseConstructor(None))
3311 },
3312 Some((b"3", t)) => {
3313 tail = t;
3314 Ok(CtorDtorName::CompleteAllocatingConstructor(None))
3315 },
3316 Some((b"4", t)) => {
3317 tail = t;
3318 Ok(CtorDtorName::MaybeInChargeConstructor(None))
3319 },
3320 _ => Err(error::Error::UnexpectedText),
3321 }?;
3322
3323 if inheriting {
3324 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3325 *ctor_type.inheriting_mut() = Some(ty);
3326 Ok((ctor_type, tail))
3327 } else {
3328 Ok((ctor_type, tail))
3329 }
3330 }
3331 Some(b'D') => {
3332 match input
3333 .try_split_at(2)
3334 .as_ref()
3335 .map(|&(ref h, t)| (h.as_ref(), t))
3336 {
3337 Some((b"D0", tail)) => Ok((CtorDtorName::DeletingDestructor, tail)),
3338 Some((b"D1", tail)) => Ok((CtorDtorName::CompleteDestructor, tail)),
3339 Some((b"D2", tail)) => Ok((CtorDtorName::BaseDestructor, tail)),
3340 Some((b"D4", tail)) => Ok((CtorDtorName::MaybeInChargeDestructor, tail)),
3341 _ => Err(error::Error::UnexpectedText),
3342 }
3343 }
3344 None => Err(error::Error::UnexpectedEnd),
3345 _ => Err(error::Error::UnexpectedText),
3346 }
3347 }
3348 }
3349
3350 impl<'subs, W> Demangle<'subs, W> for CtorDtorName
3351 where
3352 W: 'subs + DemangleWrite,
3353 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result3354 fn demangle<'prev, 'ctx>(
3355 &'subs self,
3356 ctx: &'ctx mut DemangleContext<'subs, W>,
3357 scope: Option<ArgScopeStack<'prev, 'subs>>,
3358 ) -> fmt::Result {
3359 let ctx = try_begin_demangle!(self, ctx, scope);
3360
3361 let leaf = scope
3362 .leaf_name()
3363 .map_err(|e| {
3364 log!("Error getting leaf name: {}", e);
3365 fmt::Error
3366 })?;
3367
3368 match *self {
3369 CtorDtorName::CompleteConstructor(ref inheriting)
3370 | CtorDtorName::BaseConstructor(ref inheriting)
3371 | CtorDtorName::CompleteAllocatingConstructor(ref inheriting)
3372 | CtorDtorName::MaybeInChargeConstructor(ref inheriting) => {
3373 match inheriting {
3374 Some(ty) => ty.get_leaf_name(ctx.subs).ok_or_else(|| {
3375 log!("Error getting leaf name: {:?}", ty);
3376 fmt::Error
3377 })?.demangle_as_leaf(ctx),
3378 None => leaf.demangle_as_leaf(ctx),
3379 }
3380 },
3381 CtorDtorName::DeletingDestructor
3382 | CtorDtorName::CompleteDestructor
3383 | CtorDtorName::BaseDestructor
3384 | CtorDtorName::MaybeInChargeDestructor => {
3385 write!(ctx, "~")?;
3386 leaf.demangle_as_leaf(ctx)
3387 }
3388 }
3389 }
3390 }
3391
3392 impl CtorDtorName {
3393 #[inline]
starts_with(byte: u8) -> bool3394 fn starts_with(byte: u8) -> bool {
3395 byte == b'C' || byte == b'D'
3396 }
3397 }
3398
3399 /// The `<type>` production.
3400 ///
3401 /// ```text
3402 /// <type> ::= <builtin-type>
3403 /// ::= <function-type>
3404 /// ::= <class-enum-type>
3405 /// ::= <array-type>
3406 /// ::= <vector-type>
3407 /// ::= <pointer-to-member-type>
3408 /// ::= <template-param>
3409 /// ::= <template-template-param> <template-args>
3410 /// ::= <decltype>
3411 /// ::= <CV-qualifiers> <type>
3412 /// ::= P <type> # pointer-to
3413 /// ::= R <type> # reference-to
3414 /// ::= O <type> # rvalue reference-to (C++0x)
3415 /// ::= C <type> # complex pair (C 2000)
3416 /// ::= G <type> # imaginary (C 2000)
3417 /// ::= U <source-name> [<template-args>] <type> # vendor extended type qualifier
3418 /// ::= Dp <type> # pack expansion (C++0x)
3419 /// ::= <substitution>
3420 /// ```
3421 #[derive(Clone, Debug, PartialEq, Eq)]
3422 #[allow(clippy::large_enum_variant)]
3423 pub enum Type {
3424 /// A function type.
3425 Function(FunctionType),
3426
3427 /// A class, union, or enum type.
3428 ClassEnum(ClassEnumType),
3429
3430 /// An array type.
3431 Array(ArrayType),
3432
3433 /// A vector type.
3434 Vector(VectorType),
3435
3436 /// A pointer-to-member type.
3437 PointerToMember(PointerToMemberType),
3438
3439 /// A named template parameter type.
3440 TemplateParam(TemplateParam),
3441
3442 /// A template template type.
3443 TemplateTemplate(TemplateTemplateParamHandle, TemplateArgs),
3444
3445 /// A decltype.
3446 Decltype(Decltype),
3447
3448 /// A const-, restrict-, and/or volatile-qualified type.
3449 Qualified(CvQualifiers, TypeHandle),
3450
3451 /// A pointer to a type.
3452 PointerTo(TypeHandle),
3453
3454 /// An lvalue reference to a type.
3455 LvalueRef(TypeHandle),
3456
3457 /// An rvalue reference to a type.
3458 RvalueRef(TypeHandle),
3459
3460 /// A complex pair of the given type.
3461 Complex(TypeHandle),
3462
3463 /// An imaginary of the given type.
3464 Imaginary(TypeHandle),
3465
3466 /// A vendor extended type qualifier.
3467 VendorExtension(SourceName, Option<TemplateArgs>, TypeHandle),
3468
3469 /// A pack expansion.
3470 PackExpansion(TypeHandle),
3471 }
3472
3473 define_handle! {
3474 /// A reference to a parsed `Type` production.
3475 pub enum TypeHandle {
3476 /// A builtin type. These don't end up in the substitutions table.
3477 extra Builtin(BuiltinType),
3478
3479 /// A CV-qualified builtin type. These don't end up in the table either.
3480 extra QualifiedBuiltin(QualifiedBuiltin),
3481 }
3482 }
3483
3484 impl TypeHandle {
is_void(&self) -> bool3485 fn is_void(&self) -> bool {
3486 match *self {
3487 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Void)) => true,
3488 _ => false,
3489 }
3490 }
3491 }
3492
3493 impl Parse for TypeHandle {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(TypeHandle, IndexStr<'b>)>3494 fn parse<'a, 'b>(
3495 ctx: &'a ParseContext,
3496 subs: &'a mut SubstitutionTable,
3497 input: IndexStr<'b>,
3498 ) -> Result<(TypeHandle, IndexStr<'b>)> {
3499 try_begin_parse!("TypeHandle", ctx, input);
3500
3501 /// Insert the given type into the substitution table, and return a
3502 /// handle referencing the index in the table where it ended up.
3503 fn insert_and_return_handle<'a, 'b>(
3504 ty: Type,
3505 subs: &'a mut SubstitutionTable,
3506 tail: IndexStr<'b>,
3507 ) -> Result<(TypeHandle, IndexStr<'b>)> {
3508 let ty = Substitutable::Type(ty);
3509 let idx = subs.insert(ty);
3510 let handle = TypeHandle::BackReference(idx);
3511 Ok((handle, tail))
3512 }
3513
3514 if let Ok((builtin, tail)) = BuiltinType::parse(ctx, subs, input) {
3515 // Builtin types are one of two exceptions that do not end up in the
3516 // substitutions table.
3517 let handle = TypeHandle::Builtin(builtin);
3518 return Ok((handle, tail));
3519 }
3520
3521 if let Ok((ty, tail)) = ClassEnumType::parse(ctx, subs, input) {
3522 let ty = Type::ClassEnum(ty);
3523 return insert_and_return_handle(ty, subs, tail);
3524 }
3525
3526 if let Ok((sub, tail)) = Substitution::parse(ctx, subs, input) {
3527 // If we see an 'I', then this is actually a substitution for a
3528 // <template-template-param>, and the template args are what
3529 // follows. Throw away what we just parsed, and re-parse it in
3530 // `TemplateTemplateParamHandle::parse` for now, but it would be
3531 // nice not to duplicate work we've already done.
3532 if tail.peek() != Some(b'I') {
3533 match sub {
3534 Substitution::WellKnown(component) => {
3535 return Ok((TypeHandle::WellKnown(component), tail));
3536 }
3537 Substitution::BackReference(idx) => {
3538 // TODO: should this check if the back reference actually points
3539 // to a <type>?
3540 return Ok((TypeHandle::BackReference(idx), tail));
3541 }
3542 }
3543 }
3544 }
3545
3546 if let Ok((funty, tail)) = FunctionType::parse(ctx, subs, input) {
3547 let ty = Type::Function(funty);
3548 return insert_and_return_handle(ty, subs, tail);
3549 }
3550
3551 if let Ok((ty, tail)) = ArrayType::parse(ctx, subs, input) {
3552 let ty = Type::Array(ty);
3553 return insert_and_return_handle(ty, subs, tail);
3554 }
3555
3556 if let Ok((ty, tail)) = VectorType::parse(ctx, subs, input) {
3557 let ty = Type::Vector(ty);
3558 return insert_and_return_handle(ty, subs, tail);
3559 }
3560
3561 if let Ok((ty, tail)) = PointerToMemberType::parse(ctx, subs, input) {
3562 let ty = Type::PointerToMember(ty);
3563 return insert_and_return_handle(ty, subs, tail);
3564 }
3565
3566 if let Ok((param, tail)) = TemplateParam::parse(ctx, subs, input) {
3567 // Same situation as with `Substitution::parse` at the top of this
3568 // function: this is actually a <template-template-param> and
3569 // <template-args>.
3570 if tail.peek() != Some(b'I') {
3571 let ty = Type::TemplateParam(param);
3572 return insert_and_return_handle(ty, subs, tail);
3573 } else if ctx.in_conversion() {
3574 // This may be <template-template-param> <template-args>.
3575 // But if we're here for a conversion operator, that's only
3576 // possible if the grammar looks like:
3577 //
3578 // <nested-name>
3579 // -> <source-name> cv <template-template-param> <template-args> <template-args>
3580 //
3581 // That is, there must be *another* <template-args> production after ours.
3582 // If there isn't one, then this really is a <template-param>.
3583 //
3584 // NB: Parsing a <template-args> production may modify the substitutions
3585 // table, so we need to avoid contaminating the official copy.
3586 let mut tmp_subs = subs.clone();
3587 if let Ok((_, new_tail)) = TemplateArgs::parse(ctx, &mut tmp_subs, tail) {
3588 if new_tail.peek() != Some(b'I') {
3589 // Don't consume the TemplateArgs.
3590 let ty = Type::TemplateParam(param);
3591 return insert_and_return_handle(ty, subs, tail);
3592 }
3593 // We really do have a <template-template-param>. Fall through.
3594 // NB: We can't use the arguments we just parsed because a
3595 // TemplateTemplateParam is substitutable, and if we use it
3596 // any substitutions in the arguments will come *before* it,
3597 // putting the substitution table out of order.
3598 }
3599 }
3600 }
3601
3602 if let Ok((ttp, tail)) = TemplateTemplateParamHandle::parse(ctx, subs, input) {
3603 let (args, tail) = TemplateArgs::parse(ctx, subs, tail)?;
3604 let ty = Type::TemplateTemplate(ttp, args);
3605 return insert_and_return_handle(ty, subs, tail);
3606 }
3607
3608 if let Ok((param, tail)) = Decltype::parse(ctx, subs, input) {
3609 let ty = Type::Decltype(param);
3610 return insert_and_return_handle(ty, subs, tail);
3611 }
3612
3613 if let Ok((qualifiers, tail)) = CvQualifiers::parse(ctx, subs, input) {
3614 // CvQualifiers can parse successfully without consuming any input,
3615 // but we don't want to recurse unless we know we did consume some
3616 // input, lest we go into an infinite loop and blow the stack.
3617 if tail.len() < input.len() {
3618 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3619 let ty = Type::Qualified(qualifiers, ty);
3620 return insert_and_return_handle(ty, subs, tail);
3621 }
3622 }
3623
3624 if let Ok(tail) = consume(b"P", input) {
3625 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3626 let ty = Type::PointerTo(ty);
3627 return insert_and_return_handle(ty, subs, tail);
3628 }
3629
3630 if let Ok(tail) = consume(b"R", input) {
3631 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3632 let ty = Type::LvalueRef(ty);
3633 return insert_and_return_handle(ty, subs, tail);
3634 }
3635
3636 if let Ok(tail) = consume(b"O", input) {
3637 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3638 let ty = Type::RvalueRef(ty);
3639 return insert_and_return_handle(ty, subs, tail);
3640 }
3641
3642 if let Ok(tail) = consume(b"C", input) {
3643 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3644 let ty = Type::Complex(ty);
3645 return insert_and_return_handle(ty, subs, tail);
3646 }
3647
3648 if let Ok(tail) = consume(b"G", input) {
3649 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3650 let ty = Type::Imaginary(ty);
3651 return insert_and_return_handle(ty, subs, tail);
3652 }
3653
3654 if let Ok(tail) = consume(b"U", input) {
3655 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
3656 let (args, tail) = if let Ok((args, tail)) = TemplateArgs::parse(ctx, subs, tail) {
3657 (Some(args), tail)
3658 } else {
3659 (None, tail)
3660 };
3661 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3662 let ty = Type::VendorExtension(name, args, ty);
3663 return insert_and_return_handle(ty, subs, tail);
3664 }
3665
3666 let tail = consume(b"Dp", input)?;
3667 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3668 let ty = Type::PackExpansion(ty);
3669 insert_and_return_handle(ty, subs, tail)
3670 }
3671 }
3672
3673 impl GetTemplateArgs for TypeHandle {
get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>3674 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
3675 subs.get_type(self)
3676 .and_then(|ty| ty.get_template_args(subs))
3677 }
3678 }
3679
3680 impl<'subs, W> Demangle<'subs, W> for Type
3681 where
3682 W: 'subs + DemangleWrite,
3683 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result3684 fn demangle<'prev, 'ctx>(
3685 &'subs self,
3686 ctx: &'ctx mut DemangleContext<'subs, W>,
3687 scope: Option<ArgScopeStack<'prev, 'subs>>,
3688 ) -> fmt::Result {
3689 let ctx = try_begin_demangle!(self, ctx, scope);
3690
3691 match *self {
3692 Type::Function(ref func_ty) => func_ty.demangle(ctx, scope),
3693 Type::ClassEnum(ref cls_enum_ty) => cls_enum_ty.demangle(ctx, scope),
3694 Type::Array(ref array_ty) => array_ty.demangle(ctx, scope),
3695 Type::Vector(ref vector_ty) => vector_ty.demangle(ctx, scope),
3696 Type::PointerToMember(ref ptm) => ptm.demangle(ctx, scope),
3697 Type::TemplateParam(ref param) => param.demangle(ctx, scope),
3698 Type::TemplateTemplate(ref tt_param, ref args) => {
3699 tt_param.demangle(ctx, scope)?;
3700 args.demangle(ctx, scope)
3701 }
3702 Type::Decltype(ref dt) => dt.demangle(ctx, scope),
3703 Type::Qualified(_, ref ty) => {
3704 ctx.push_inner(self);
3705 ty.demangle(ctx, scope)?;
3706 if ctx.pop_inner_if(self) {
3707 self.demangle_as_inner(ctx, scope)?;
3708 }
3709 Ok(())
3710 }
3711 Type::PointerTo(ref ty) | Type::LvalueRef(ref ty) | Type::RvalueRef(ref ty) => {
3712 ctx.push_inner(self);
3713 ty.demangle(ctx, scope)?;
3714 if ctx.pop_inner_if(self) {
3715 self.demangle_as_inner(ctx, scope)?;
3716 }
3717 Ok(())
3718 }
3719 Type::Complex(ref ty) => {
3720 ty.demangle(ctx, scope)?;
3721 write!(ctx, " complex")?;
3722 Ok(())
3723 }
3724 Type::Imaginary(ref ty) => {
3725 ty.demangle(ctx, scope)?;
3726 write!(ctx, " imaginary")?;
3727 Ok(())
3728 }
3729 Type::VendorExtension(ref name, ref template_args, ref ty) => {
3730 ty.demangle(ctx, scope)?;
3731 write!(ctx, " ")?;
3732 name.demangle(ctx, scope)?;
3733 if let Some(ref args) = *template_args {
3734 args.demangle(ctx, scope)?;
3735 }
3736 Ok(())
3737 }
3738 Type::PackExpansion(ref ty) => {
3739 ty.demangle(ctx, scope)?;
3740 if !ctx.is_template_argument_pack {
3741 write!(ctx, "...")?;
3742 }
3743 Ok(())
3744 }
3745 }
3746 }
3747 }
3748
3749 impl<'subs, W> DemangleAsInner<'subs, W> for Type
3750 where
3751 W: 'subs + DemangleWrite,
3752 {
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result3753 fn demangle_as_inner<'prev, 'ctx>(
3754 &'subs self,
3755 ctx: &'ctx mut DemangleContext<'subs, W>,
3756 scope: Option<ArgScopeStack<'prev, 'subs>>,
3757 ) -> fmt::Result {
3758 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
3759
3760 match *self {
3761 Type::Qualified(ref quals, _) => quals.demangle_as_inner(ctx, scope),
3762 Type::PointerTo(_) => write!(ctx, "*"),
3763 Type::LvalueRef(_) => write!(ctx, "&"),
3764 Type::RvalueRef(_) => write!(ctx, "&&"),
3765 ref otherwise => {
3766 unreachable!(
3767 "We shouldn't ever put any other types on the inner stack: {:?}",
3768 otherwise
3769 );
3770 }
3771 }
3772 }
3773
downcast_to_type(&self) -> Option<&Type>3774 fn downcast_to_type(&self) -> Option<&Type> {
3775 Some(self)
3776 }
3777
downcast_to_function_type(&self) -> Option<&FunctionType>3778 fn downcast_to_function_type(&self) -> Option<&FunctionType> {
3779 if let Type::Function(ref f) = *self {
3780 Some(f)
3781 } else {
3782 None
3783 }
3784 }
3785
downcast_to_array_type(&self) -> Option<&ArrayType>3786 fn downcast_to_array_type(&self) -> Option<&ArrayType> {
3787 if let Type::Array(ref arr) = *self {
3788 Some(arr)
3789 } else {
3790 None
3791 }
3792 }
3793
downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType>3794 fn downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType> {
3795 if let Type::PointerToMember(ref ptm) = *self {
3796 Some(ptm)
3797 } else {
3798 None
3799 }
3800 }
3801
is_qualified(&self) -> bool3802 fn is_qualified(&self) -> bool {
3803 match *self {
3804 Type::Qualified(..) => true,
3805 _ => false,
3806 }
3807 }
3808 }
3809
3810 impl GetTemplateArgs for Type {
get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>3811 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
3812 // TODO: This should probably recurse through all the nested type
3813 // handles too.
3814
3815 match *self {
3816 Type::VendorExtension(_, Some(ref args), _) | Type::TemplateTemplate(_, ref args) => {
3817 Some(args)
3818 }
3819 Type::PointerTo(ref ty) | Type::LvalueRef(ref ty) | Type::RvalueRef(ref ty) => {
3820 ty.get_template_args(subs)
3821 }
3822 _ => None,
3823 }
3824 }
3825 }
3826
3827 impl<'a> GetLeafName<'a> for Type {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>3828 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
3829 match *self {
3830 Type::ClassEnum(ref cls_enum_ty) => cls_enum_ty.get_leaf_name(subs),
3831 _ => None,
3832 }
3833 }
3834 }
3835
3836 /// The `<CV-qualifiers>` production.
3837 ///
3838 /// ```text
3839 /// <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
3840 /// ```
3841 #[derive(Clone, Debug, Default, Hash, PartialEq, Eq)]
3842 pub struct CvQualifiers {
3843 /// Is this `restrict` qualified?
3844 pub restrict: bool,
3845 /// Is this `volatile` qualified?
3846 pub volatile: bool,
3847 /// Is this `const` qualified?
3848 pub const_: bool,
3849 }
3850
3851 impl CvQualifiers {
3852 #[inline]
is_empty(&self) -> bool3853 fn is_empty(&self) -> bool {
3854 !self.restrict && !self.volatile && !self.const_
3855 }
3856 }
3857
3858 impl Parse for CvQualifiers {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(CvQualifiers, IndexStr<'b>)>3859 fn parse<'a, 'b>(
3860 ctx: &'a ParseContext,
3861 _subs: &'a mut SubstitutionTable,
3862 input: IndexStr<'b>,
3863 ) -> Result<(CvQualifiers, IndexStr<'b>)> {
3864 try_begin_parse!("CvQualifiers", ctx, input);
3865
3866 let (restrict, tail) = if let Ok(tail) = consume(b"r", input) {
3867 (true, tail)
3868 } else {
3869 (false, input)
3870 };
3871
3872 let (volatile, tail) = if let Ok(tail) = consume(b"V", tail) {
3873 (true, tail)
3874 } else {
3875 (false, tail)
3876 };
3877
3878 let (const_, tail) = if let Ok(tail) = consume(b"K", tail) {
3879 (true, tail)
3880 } else {
3881 (false, tail)
3882 };
3883
3884 let qualifiers = CvQualifiers {
3885 restrict: restrict,
3886 volatile: volatile,
3887 const_: const_,
3888 };
3889
3890 Ok((qualifiers, tail))
3891 }
3892 }
3893
3894 impl<'subs, W> Demangle<'subs, W> for CvQualifiers
3895 where
3896 W: 'subs + DemangleWrite,
3897 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result3898 fn demangle<'prev, 'ctx>(
3899 &'subs self,
3900 ctx: &'ctx mut DemangleContext<'subs, W>,
3901 scope: Option<ArgScopeStack<'prev, 'subs>>,
3902 ) -> fmt::Result {
3903 let ctx = try_begin_demangle!(self, ctx, scope);
3904
3905 if self.const_ {
3906 ctx.ensure_space()?;
3907 write!(ctx, "const")?;
3908 }
3909
3910 if self.volatile {
3911 ctx.ensure_space()?;
3912 write!(ctx, "volatile")?;
3913 }
3914
3915 if self.restrict {
3916 ctx.ensure_space()?;
3917 write!(ctx, "restrict")?;
3918 }
3919
3920 Ok(())
3921 }
3922 }
3923
3924 impl<'subs, W> DemangleAsInner<'subs, W> for CvQualifiers
3925 where
3926 W: 'subs + DemangleWrite,
3927 {
3928 }
3929
3930 define_vocabulary! {
3931 /// A <ref-qualifier> production.
3932 ///
3933 /// ```text
3934 /// <ref-qualifier> ::= R # & ref-qualifier
3935 /// ::= O # && ref-qualifier
3936 /// ```
3937 #[derive(Clone, Debug, PartialEq, Eq)]
3938 pub enum RefQualifier {
3939 LValueRef(b"R", "&"),
3940 RValueRef(b"O", "&&")
3941 }
3942 }
3943
3944 define_vocabulary! {
3945 /// A one of the standard variants of the <builtin-type> production.
3946 ///
3947 /// ```text
3948 /// <builtin-type> ::= v # void
3949 /// ::= w # wchar_t
3950 /// ::= b # bool
3951 /// ::= c # char
3952 /// ::= a # signed char
3953 /// ::= h # unsigned char
3954 /// ::= s # short
3955 /// ::= t # unsigned short
3956 /// ::= i # int
3957 /// ::= j # unsigned int
3958 /// ::= l # long
3959 /// ::= m # unsigned long
3960 /// ::= x # long long, __int64
3961 /// ::= y # unsigned long long, __int64
3962 /// ::= n # __int128
3963 /// ::= o # unsigned __int128
3964 /// ::= f # float
3965 /// ::= d # double
3966 /// ::= e # long double, __float80
3967 /// ::= g # __float128
3968 /// ::= z # ellipsis
3969 /// ::= Dd # IEEE 754r decimal floating point (64 bits)
3970 /// ::= De # IEEE 754r decimal floating point (128 bits)
3971 /// ::= Df # IEEE 754r decimal floating point (32 bits)
3972 /// ::= Dh # IEEE 754r half-precision floating point (16 bits)
3973 /// ::= Di # char32_t
3974 /// ::= Ds # char16_t
3975 /// ::= Da # auto
3976 /// ::= Dc # decltype(auto)
3977 /// ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3978 /// ```
3979 #[derive(Clone, Debug, PartialEq, Eq)]
3980 pub enum StandardBuiltinType {
3981 Void (b"v", "void"),
3982 Wchar (b"w", "wchar_t"),
3983 Bool (b"b", "bool"),
3984 Char (b"c", "char"),
3985 SignedChar (b"a", "signed char"),
3986 UnsignedChar (b"h", "unsigned char"),
3987 Short (b"s", "short"),
3988 UnsignedShort (b"t", "unsigned short"),
3989 Int (b"i", "int"),
3990 UnsignedInt (b"j", "unsigned int"),
3991 Long (b"l", "long"),
3992 UnsignedLong (b"m", "unsigned long"),
3993 LongLong (b"x", "long long"),
3994 UnsignedLongLong (b"y", "unsigned long long"),
3995 Int128 (b"n", "__int128"),
3996 Uint128 (b"o", "unsigned __int128"),
3997 Float (b"f", "float"),
3998 Double (b"d", "double"),
3999 LongDouble (b"e", "long double"),
4000 Float128 (b"g", "__float128"),
4001 Ellipsis (b"z", "..."),
4002 DecimalFloat64 (b"Dd", "decimal64"),
4003 DecimalFloat128 (b"De", "decimal128"),
4004 DecimalFloat32 (b"Df", "decimal32"),
4005 DecimalFloat16 (b"Dh", "half"),
4006 Char32 (b"Di", "char32_t"),
4007 Char16 (b"Ds", "char16_t"),
4008 Auto (b"Da", "auto"),
4009 Decltype (b"Dc", "decltype(auto)"),
4010 Nullptr (b"Dn", "std::nullptr_t")
4011 }
4012 }
4013
4014 /// The `<builtin-type>` production.
4015 #[derive(Clone, Debug, PartialEq, Eq)]
4016 pub enum BuiltinType {
4017 /// A standards compliant builtin type.
4018 Standard(StandardBuiltinType),
4019
4020 /// A non-standard, vendor extension type.
4021 ///
4022 /// ```text
4023 /// <builtin-type> ::= u <source-name> # vendor extended type
4024 /// ```
4025 Extension(SourceName),
4026 }
4027
4028 impl Parse for BuiltinType {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(BuiltinType, IndexStr<'b>)>4029 fn parse<'a, 'b>(
4030 ctx: &'a ParseContext,
4031 subs: &'a mut SubstitutionTable,
4032 input: IndexStr<'b>,
4033 ) -> Result<(BuiltinType, IndexStr<'b>)> {
4034 try_begin_parse!("BuiltinType", ctx, input);
4035
4036 if let Ok((ty, tail)) = StandardBuiltinType::parse(ctx, subs, input) {
4037 return Ok((BuiltinType::Standard(ty), tail));
4038 }
4039
4040 let tail = consume(b"u", input)?;
4041 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
4042 Ok((BuiltinType::Extension(name), tail))
4043 }
4044 }
4045
4046 impl<'subs, W> Demangle<'subs, W> for BuiltinType
4047 where
4048 W: 'subs + DemangleWrite,
4049 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4050 fn demangle<'prev, 'ctx>(
4051 &'subs self,
4052 ctx: &'ctx mut DemangleContext<'subs, W>,
4053 scope: Option<ArgScopeStack<'prev, 'subs>>,
4054 ) -> fmt::Result {
4055 let ctx = try_begin_demangle!(self, ctx, scope);
4056
4057 match *self {
4058 BuiltinType::Standard(ref ty) => ty.demangle(ctx, scope),
4059 BuiltinType::Extension(ref name) => name.demangle(ctx, scope),
4060 }
4061 }
4062 }
4063
4064 impl<'a> GetLeafName<'a> for BuiltinType {
get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>>4065 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
4066 None
4067 }
4068 }
4069
4070 /// A built-in type with CV-qualifiers.
4071 ///
4072 /// Like unqualified built-in types, CV-qualified built-in types do not go into
4073 /// the substitutions table.
4074 #[derive(Clone, Debug, PartialEq, Eq)]
4075 pub struct QualifiedBuiltin(CvQualifiers, BuiltinType);
4076
4077 impl<'subs, W> Demangle<'subs, W> for QualifiedBuiltin
4078 where
4079 W: 'subs + DemangleWrite,
4080 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4081 fn demangle<'prev, 'ctx>(
4082 &'subs self,
4083 ctx: &'ctx mut DemangleContext<'subs, W>,
4084 scope: Option<ArgScopeStack<'prev, 'subs>>,
4085 ) -> fmt::Result {
4086 let ctx = try_begin_demangle!(self, ctx, scope);
4087
4088 ctx.push_inner(&self.0);
4089 self.1.demangle(ctx, scope)?;
4090 if ctx.pop_inner_if(&self.0) {
4091 self.0.demangle_as_inner(ctx, scope)?;
4092 }
4093 Ok(())
4094 }
4095 }
4096
4097 impl<'a> GetLeafName<'a> for QualifiedBuiltin {
get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>>4098 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
4099 None
4100 }
4101 }
4102
4103 /// The `<function-type>` production.
4104 ///
4105 /// ```text
4106 /// <function-type> ::= [<CV-qualifiers>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
4107 /// ```
4108 #[derive(Clone, Debug, PartialEq, Eq)]
4109 pub struct FunctionType {
4110 cv_qualifiers: CvQualifiers,
4111 transaction_safe: bool,
4112 extern_c: bool,
4113 bare: BareFunctionType,
4114 ref_qualifier: Option<RefQualifier>,
4115 }
4116
4117 impl Parse for FunctionType {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(FunctionType, IndexStr<'b>)>4118 fn parse<'a, 'b>(
4119 ctx: &'a ParseContext,
4120 subs: &'a mut SubstitutionTable,
4121 input: IndexStr<'b>,
4122 ) -> Result<(FunctionType, IndexStr<'b>)> {
4123 try_begin_parse!("FunctionType", ctx, input);
4124
4125 let (cv_qualifiers, tail) =
4126 if let Ok((cv_qualifiers, tail)) = CvQualifiers::parse(ctx, subs, input) {
4127 (cv_qualifiers, tail)
4128 } else {
4129 (Default::default(), input)
4130 };
4131
4132 let (transaction_safe, tail) = if let Ok(tail) = consume(b"Dx", tail) {
4133 (true, tail)
4134 } else {
4135 (false, tail)
4136 };
4137
4138 let tail = consume(b"F", tail)?;
4139
4140 let (extern_c, tail) = if let Ok(tail) = consume(b"Y", tail) {
4141 (true, tail)
4142 } else {
4143 (false, tail)
4144 };
4145
4146 let (bare, tail) = BareFunctionType::parse(ctx, subs, tail)?;
4147
4148 let (ref_qualifier, tail) =
4149 if let Ok((ref_qualifier, tail)) = RefQualifier::parse(ctx, subs, tail) {
4150 (Some(ref_qualifier), tail)
4151 } else {
4152 (None, tail)
4153 };
4154
4155 let tail = consume(b"E", tail)?;
4156
4157 let func_ty = FunctionType {
4158 cv_qualifiers: cv_qualifiers,
4159 transaction_safe: transaction_safe,
4160 extern_c: extern_c,
4161 bare: bare,
4162 ref_qualifier: ref_qualifier,
4163 };
4164 Ok((func_ty, tail))
4165 }
4166 }
4167
4168 impl<'subs, W> Demangle<'subs, W> for FunctionType
4169 where
4170 W: 'subs + DemangleWrite,
4171 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4172 fn demangle<'prev, 'ctx>(
4173 &'subs self,
4174 ctx: &'ctx mut DemangleContext<'subs, W>,
4175 scope: Option<ArgScopeStack<'prev, 'subs>>,
4176 ) -> fmt::Result {
4177 let ctx = try_begin_demangle!(self, ctx, scope);
4178
4179 ctx.push_inner(self);
4180 self.bare.demangle(ctx, scope)?;
4181 if ctx.pop_inner_if(self) {
4182 self.demangle_as_inner(ctx, scope)?;
4183 }
4184 Ok(())
4185 }
4186 }
4187
4188 impl<'subs, W> DemangleAsInner<'subs, W> for FunctionType
4189 where
4190 W: 'subs + DemangleWrite,
4191 {
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4192 fn demangle_as_inner<'prev, 'ctx>(
4193 &'subs self,
4194 ctx: &'ctx mut DemangleContext<'subs, W>,
4195 scope: Option<ArgScopeStack<'prev, 'subs>>,
4196 ) -> fmt::Result {
4197 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4198
4199 if !self.cv_qualifiers.is_empty() {
4200 self.cv_qualifiers.demangle(ctx, scope)?;
4201 }
4202
4203 if let Some(ref rq) = self.ref_qualifier {
4204 // Print out a space before printing "&" or "&&"
4205 ctx.ensure_space()?;
4206 rq.demangle(ctx, scope)?;
4207 }
4208
4209 Ok(())
4210 }
4211
downcast_to_function_type(&self) -> Option<&FunctionType>4212 fn downcast_to_function_type(&self) -> Option<&FunctionType> {
4213 Some(self)
4214 }
4215 }
4216
4217 /// The `<bare-function-type>` production.
4218 ///
4219 /// ```text
4220 /// <bare-function-type> ::= <signature type>+
4221 /// # types are possible return type, then parameter types
4222 /// ```
4223 #[derive(Clone, Debug, PartialEq, Eq)]
4224 pub struct BareFunctionType(Vec<TypeHandle>);
4225
4226 impl BareFunctionType {
ret(&self) -> &TypeHandle4227 fn ret(&self) -> &TypeHandle {
4228 &self.0[0]
4229 }
4230
args(&self) -> &FunctionArgListAndReturnType4231 fn args(&self) -> &FunctionArgListAndReturnType {
4232 FunctionArgListAndReturnType::new(&self.0)
4233 }
4234 }
4235
4236 impl Parse for BareFunctionType {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(BareFunctionType, IndexStr<'b>)>4237 fn parse<'a, 'b>(
4238 ctx: &'a ParseContext,
4239 subs: &'a mut SubstitutionTable,
4240 input: IndexStr<'b>,
4241 ) -> Result<(BareFunctionType, IndexStr<'b>)> {
4242 try_begin_parse!("BareFunctionType", ctx, input);
4243
4244 let (types, tail) = one_or_more::<TypeHandle>(ctx, subs, input)?;
4245 Ok((BareFunctionType(types), tail))
4246 }
4247 }
4248
4249 impl<'subs, W> Demangle<'subs, W> for BareFunctionType
4250 where
4251 W: 'subs + DemangleWrite,
4252 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4253 fn demangle<'prev, 'ctx>(
4254 &'subs self,
4255 ctx: &'ctx mut DemangleContext<'subs, W>,
4256 scope: Option<ArgScopeStack<'prev, 'subs>>,
4257 ) -> fmt::Result {
4258 let ctx = try_begin_demangle!(self, ctx, scope);
4259
4260 ctx.push_inner(self);
4261
4262 self.ret().demangle(ctx, scope)?;
4263
4264 if ctx.pop_inner_if(self) {
4265 ctx.ensure_space()?;
4266 self.demangle_as_inner(ctx, scope)?;
4267 }
4268
4269 Ok(())
4270 }
4271 }
4272
4273 impl<'subs, W> DemangleAsInner<'subs, W> for BareFunctionType
4274 where
4275 W: 'subs + DemangleWrite,
4276 {
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4277 fn demangle_as_inner<'prev, 'ctx>(
4278 &'subs self,
4279 ctx: &'ctx mut DemangleContext<'subs, W>,
4280 scope: Option<ArgScopeStack<'prev, 'subs>>,
4281 ) -> fmt::Result {
4282 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4283 self.args().demangle_as_inner(ctx, scope)?;
4284 Ok(())
4285 }
4286 }
4287
4288 /// The `<decltype>` production.
4289 ///
4290 /// ```text
4291 /// <decltype> ::= Dt <expression> E
4292 /// ::= DT <expression> E
4293 /// ```
4294 #[derive(Clone, Debug, PartialEq, Eq)]
4295 pub enum Decltype {
4296 /// A `decltype` of an id-expression or class member access (C++0x).
4297 IdExpression(Expression),
4298
4299 /// A `decltype` of an expression (C++0x).
4300 Expression(Expression),
4301 }
4302
4303 impl Parse for Decltype {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Decltype, IndexStr<'b>)>4304 fn parse<'a, 'b>(
4305 ctx: &'a ParseContext,
4306 subs: &'a mut SubstitutionTable,
4307 input: IndexStr<'b>,
4308 ) -> Result<(Decltype, IndexStr<'b>)> {
4309 try_begin_parse!("Decltype", ctx, input);
4310
4311 let tail = consume(b"D", input)?;
4312
4313 if let Ok(tail) = consume(b"t", tail) {
4314 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
4315 let tail = consume(b"E", tail)?;
4316 return Ok((Decltype::IdExpression(expr), tail));
4317 }
4318
4319 let tail = consume(b"T", tail)?;
4320 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
4321 let tail = consume(b"E", tail)?;
4322 Ok((Decltype::Expression(expr), tail))
4323 }
4324 }
4325
4326 impl<'subs, W> Demangle<'subs, W> for Decltype
4327 where
4328 W: 'subs + DemangleWrite,
4329 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4330 fn demangle<'prev, 'ctx>(
4331 &'subs self,
4332 ctx: &'ctx mut DemangleContext<'subs, W>,
4333 scope: Option<ArgScopeStack<'prev, 'subs>>,
4334 ) -> fmt::Result {
4335 let ctx = try_begin_demangle!(self, ctx, scope);
4336
4337 ctx.push_demangle_node(DemangleNodeType::TemplateParam);
4338 let ret = match *self {
4339 Decltype::Expression(ref expr) | Decltype::IdExpression(ref expr) => {
4340 write!(ctx, "decltype (")?;
4341 expr.demangle(ctx, scope)?;
4342 write!(ctx, ")")?;
4343 Ok(())
4344 }
4345 };
4346 ctx.pop_demangle_node();
4347 ret
4348 }
4349 }
4350
4351 /// The `<class-enum-type>` production.
4352 ///
4353 /// ```text
4354 /// <class-enum-type> ::= <name>
4355 /// ::= Ts <name>
4356 /// ::= Tu <name>
4357 /// ::= Te <name>
4358 /// ```
4359 #[derive(Clone, Debug, PartialEq, Eq)]
4360 pub enum ClassEnumType {
4361 /// A non-dependent type name, dependent type name, or dependent
4362 /// typename-specifier.
4363 Named(Name),
4364
4365 /// A dependent elaborated type specifier using 'struct' or 'class'.
4366 ElaboratedStruct(Name),
4367
4368 /// A dependent elaborated type specifier using 'union'.
4369 ElaboratedUnion(Name),
4370
4371 /// A dependent elaborated type specifier using 'enum'.
4372 ElaboratedEnum(Name),
4373 }
4374
4375 impl Parse for ClassEnumType {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(ClassEnumType, IndexStr<'b>)>4376 fn parse<'a, 'b>(
4377 ctx: &'a ParseContext,
4378 subs: &'a mut SubstitutionTable,
4379 input: IndexStr<'b>,
4380 ) -> Result<(ClassEnumType, IndexStr<'b>)> {
4381 try_begin_parse!("ClassEnumType", ctx, input);
4382
4383 if let Ok((name, tail)) = Name::parse(ctx, subs, input) {
4384 return Ok((ClassEnumType::Named(name), tail));
4385 }
4386
4387 let tail = consume(b"T", input)?;
4388
4389 if let Ok(tail) = consume(b"s", tail) {
4390 let (name, tail) = Name::parse(ctx, subs, tail)?;
4391 return Ok((ClassEnumType::ElaboratedStruct(name), tail));
4392 }
4393
4394 if let Ok(tail) = consume(b"u", tail) {
4395 let (name, tail) = Name::parse(ctx, subs, tail)?;
4396 return Ok((ClassEnumType::ElaboratedUnion(name), tail));
4397 }
4398
4399 let tail = consume(b"e", tail)?;
4400 let (name, tail) = Name::parse(ctx, subs, tail)?;
4401 Ok((ClassEnumType::ElaboratedEnum(name), tail))
4402 }
4403 }
4404
4405 impl<'subs, W> Demangle<'subs, W> for ClassEnumType
4406 where
4407 W: 'subs + DemangleWrite,
4408 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4409 fn demangle<'prev, 'ctx>(
4410 &'subs self,
4411 ctx: &'ctx mut DemangleContext<'subs, W>,
4412 scope: Option<ArgScopeStack<'prev, 'subs>>,
4413 ) -> fmt::Result {
4414 let ctx = try_begin_demangle!(self, ctx, scope);
4415
4416 match *self {
4417 ClassEnumType::Named(ref name) => name.demangle(ctx, scope),
4418 ClassEnumType::ElaboratedStruct(ref name) => {
4419 write!(ctx, "class ")?;
4420 name.demangle(ctx, scope)
4421 }
4422 ClassEnumType::ElaboratedUnion(ref name) => {
4423 write!(ctx, "union ")?;
4424 name.demangle(ctx, scope)
4425 }
4426 ClassEnumType::ElaboratedEnum(ref name) => {
4427 write!(ctx, "enum ")?;
4428 name.demangle(ctx, scope)
4429 }
4430 }
4431 }
4432 }
4433
4434 impl<'a> GetLeafName<'a> for ClassEnumType {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>4435 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
4436 match *self {
4437 ClassEnumType::Named(ref name)
4438 | ClassEnumType::ElaboratedStruct(ref name)
4439 | ClassEnumType::ElaboratedUnion(ref name)
4440 | ClassEnumType::ElaboratedEnum(ref name) => {
4441 name.get_leaf_name(subs)
4442 }
4443 }
4444 }
4445 }
4446
4447 /// The `<unnamed-type-name>` production.
4448 ///
4449 /// ```text
4450 /// <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
4451 /// ::= <closure-type-name>
4452 /// ```
4453 ///
4454 /// TODO: parse the <closure-type-name> variant
4455 #[derive(Clone, Debug, PartialEq, Eq)]
4456 pub struct UnnamedTypeName(Option<usize>);
4457
4458 impl Parse for UnnamedTypeName {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(UnnamedTypeName, IndexStr<'b>)>4459 fn parse<'a, 'b>(
4460 ctx: &'a ParseContext,
4461 _subs: &'a mut SubstitutionTable,
4462 input: IndexStr<'b>,
4463 ) -> Result<(UnnamedTypeName, IndexStr<'b>)> {
4464 try_begin_parse!("UnnamedTypeName", ctx, input);
4465
4466 let input = consume(b"Ut", input)?;
4467 let (number, input) = match parse_number(10, false, input) {
4468 Ok((number, input)) => (Some(number as _), input),
4469 Err(_) => (None, input),
4470 };
4471 let input = consume(b"_", input)?;
4472 Ok((UnnamedTypeName(number), input))
4473 }
4474 }
4475
4476 impl UnnamedTypeName {
4477 #[inline]
starts_with(byte: u8) -> bool4478 fn starts_with(byte: u8) -> bool {
4479 byte == b'U'
4480 }
4481 }
4482
4483 impl<'subs, W> Demangle<'subs, W> for UnnamedTypeName
4484 where
4485 W: 'subs + DemangleWrite,
4486 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4487 fn demangle<'prev, 'ctx>(
4488 &'subs self,
4489 ctx: &'ctx mut DemangleContext<'subs, W>,
4490 scope: Option<ArgScopeStack<'prev, 'subs>>,
4491 ) -> fmt::Result {
4492 let ctx = try_begin_demangle!(self, ctx, scope);
4493
4494 write!(ctx, "{{unnamed type#{}}}", self.0.map_or(1, |n| n + 1))?;
4495 Ok(())
4496 }
4497 }
4498
4499 impl<'subs, W> DemangleAsLeaf<'subs, W> for UnnamedTypeName
4500 where
4501 W: 'subs + DemangleWrite,
4502 {
demangle_as_leaf<'me, 'ctx>( &'me self, ctx: &'ctx mut DemangleContext<'subs, W>, ) -> fmt::Result4503 fn demangle_as_leaf<'me, 'ctx>(
4504 &'me self,
4505 ctx: &'ctx mut DemangleContext<'subs, W>,
4506 ) -> fmt::Result {
4507 let ctx = try_begin_demangle!(self, ctx, None);
4508 if let Some(source_name) = ctx.source_name {
4509 write!(ctx, "{}", source_name)?;
4510 } else {
4511 write!(ctx, "{{unnamed type#{}}}", self.0.map_or(1, |n| n + 1))?;
4512 }
4513 Ok(())
4514 }
4515 }
4516
4517 impl<'subs> ArgScope<'subs, 'subs> for UnnamedTypeName {
leaf_name(&'subs self) -> Result<LeafName<'subs>>4518 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
4519 Ok(LeafName::UnnamedType(self))
4520 }
4521
get_template_arg(&'subs self, _: usize) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)>4522 fn get_template_arg(&'subs self, _: usize) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
4523 Err(error::Error::BadTemplateArgReference)
4524 }
4525
get_function_arg(&'subs self, _: usize) -> Result<&'subs Type>4526 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
4527 Err(error::Error::BadFunctionArgReference)
4528 }
4529 }
4530
4531 /// The `<array-type>` production.
4532 ///
4533 /// ```text
4534 /// <array-type> ::= A <positive dimension number> _ <element type>
4535 /// ::= A [<dimension expression>] _ <element type>
4536 /// ```
4537 #[derive(Clone, Debug, PartialEq, Eq)]
4538 pub enum ArrayType {
4539 /// An array with a number-literal dimension.
4540 DimensionNumber(usize, TypeHandle),
4541
4542 /// An array with an expression for its dimension.
4543 DimensionExpression(Expression, TypeHandle),
4544
4545 /// An array with no dimension.
4546 NoDimension(TypeHandle),
4547 }
4548
4549 impl Parse for ArrayType {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(ArrayType, IndexStr<'b>)>4550 fn parse<'a, 'b>(
4551 ctx: &'a ParseContext,
4552 subs: &'a mut SubstitutionTable,
4553 input: IndexStr<'b>,
4554 ) -> Result<(ArrayType, IndexStr<'b>)> {
4555 try_begin_parse!("ArrayType", ctx, input);
4556
4557 let tail = consume(b"A", input)?;
4558
4559 if let Ok((num, tail)) = parse_number(10, false, tail) {
4560 debug_assert!(num >= 0);
4561 let tail = consume(b"_", tail)?;
4562 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4563 return Ok((ArrayType::DimensionNumber(num as _, ty), tail));
4564 }
4565
4566 if let Ok((expr, tail)) = Expression::parse(ctx, subs, tail) {
4567 let tail = consume(b"_", tail)?;
4568 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4569 return Ok((ArrayType::DimensionExpression(expr, ty), tail));
4570 }
4571
4572 let tail = consume(b"_", tail)?;
4573 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4574 Ok((ArrayType::NoDimension(ty), tail))
4575 }
4576 }
4577
4578 impl<'subs, W> Demangle<'subs, W> for ArrayType
4579 where
4580 W: 'subs + DemangleWrite,
4581 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4582 fn demangle<'prev, 'ctx>(
4583 &'subs self,
4584 ctx: &'ctx mut DemangleContext<'subs, W>,
4585 scope: Option<ArgScopeStack<'prev, 'subs>>,
4586 ) -> fmt::Result {
4587 let ctx = try_begin_demangle!(self, ctx, scope);
4588
4589 ctx.push_inner(self);
4590
4591 match *self {
4592 ArrayType::DimensionNumber(_, ref ty)
4593 | ArrayType::DimensionExpression(_, ref ty)
4594 | ArrayType::NoDimension(ref ty) => {
4595 ty.demangle(ctx, scope)?;
4596 }
4597 }
4598
4599 if ctx.pop_inner_if(self) {
4600 self.demangle_as_inner(ctx, scope)?;
4601 }
4602
4603 Ok(())
4604 }
4605 }
4606
4607 impl<'subs, W> DemangleAsInner<'subs, W> for ArrayType
4608 where
4609 W: 'subs + DemangleWrite,
4610 {
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4611 fn demangle_as_inner<'prev, 'ctx>(
4612 &'subs self,
4613 ctx: &'ctx mut DemangleContext<'subs, W>,
4614 scope: Option<ArgScopeStack<'prev, 'subs>>,
4615 ) -> fmt::Result {
4616 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4617
4618 // Whether we should add a final space before the dimensions.
4619 let mut needs_space = true;
4620
4621 while let Some(inner) = ctx.pop_inner() {
4622 // We need to add parentheses around array inner types, unless they
4623 // are also (potentially qualified) arrays themselves, in which case
4624 // we format them as multi-dimensional arrays.
4625 let inner_is_array = match inner.downcast_to_type() {
4626 Some(&Type::Qualified(_, ref ty)) => ctx.subs.get_type(ty).map_or(false, |ty| {
4627 DemangleAsInner::<W>::downcast_to_array_type(ty).is_some()
4628 }),
4629 _ => if inner.downcast_to_array_type().is_some() {
4630 needs_space = false;
4631 true
4632 } else {
4633 false
4634 },
4635 };
4636
4637 if inner_is_array {
4638 inner.demangle_as_inner(ctx, scope)?;
4639 } else {
4640 ctx.ensure_space()?;
4641
4642 // CvQualifiers should have the parentheses printed after, not before
4643 if inner.is_qualified() {
4644 inner.demangle_as_inner(ctx, scope)?;
4645 ctx.ensure_space()?;
4646 write!(ctx, "(")?;
4647 } else {
4648 write!(ctx, "(")?;
4649 inner.demangle_as_inner(ctx, scope)?;
4650 }
4651
4652 ctx.demangle_inners(scope)?;
4653 write!(ctx, ")")?;
4654 }
4655 }
4656
4657 if needs_space {
4658 ctx.ensure_space()?;
4659 }
4660
4661 match *self {
4662 ArrayType::DimensionNumber(n, _) => {
4663 write!(ctx, "[{}]", n)?;
4664 }
4665 ArrayType::DimensionExpression(ref expr, _) => {
4666 write!(ctx, "[")?;
4667 expr.demangle(ctx, scope)?;
4668 write!(ctx, "]")?;
4669 }
4670 ArrayType::NoDimension(_) => {
4671 write!(ctx, "[]")?;
4672 }
4673 }
4674
4675 Ok(())
4676 }
4677
downcast_to_array_type(&self) -> Option<&ArrayType>4678 fn downcast_to_array_type(&self) -> Option<&ArrayType> {
4679 Some(self)
4680 }
4681 }
4682
4683 /// The `<vector-type>` production.
4684 ///
4685 /// ```text
4686 /// <vector-type> ::= Dv <number> _ <type>
4687 /// ::= Dv _ <expression> _ <type>
4688 /// ```
4689 #[derive(Clone, Debug, PartialEq, Eq)]
4690 pub enum VectorType {
4691 /// An vector with a number-literal dimension.
4692 DimensionNumber(usize, TypeHandle),
4693
4694 /// An vector with an expression for its dimension.
4695 DimensionExpression(Expression, TypeHandle),
4696 }
4697
4698 impl Parse for VectorType {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(VectorType, IndexStr<'b>)>4699 fn parse<'a, 'b>(
4700 ctx: &'a ParseContext,
4701 subs: &'a mut SubstitutionTable,
4702 input: IndexStr<'b>,
4703 ) -> Result<(VectorType, IndexStr<'b>)> {
4704 try_begin_parse!("VectorType", ctx, input);
4705
4706 let tail = consume(b"Dv", input)?;
4707
4708 if let Ok((num, tail)) = parse_number(10, false, tail) {
4709 debug_assert!(num >= 0);
4710 let tail = consume(b"_", tail)?;
4711 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4712 return Ok((VectorType::DimensionNumber(num as _, ty), tail));
4713 }
4714
4715 let tail = consume(b"_", tail)?;
4716 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
4717 let tail = consume(b"_", tail)?;
4718 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4719 Ok((VectorType::DimensionExpression(expr, ty), tail))
4720 }
4721 }
4722
4723 impl<'subs, W> Demangle<'subs, W> for VectorType
4724 where
4725 W: 'subs + DemangleWrite,
4726 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4727 fn demangle<'prev, 'ctx>(
4728 &'subs self,
4729 ctx: &'ctx mut DemangleContext<'subs, W>,
4730 scope: Option<ArgScopeStack<'prev, 'subs>>,
4731 ) -> fmt::Result {
4732 let ctx = try_begin_demangle!(self, ctx, scope);
4733
4734 ctx.push_inner(self);
4735
4736 match *self {
4737 VectorType::DimensionNumber(_, ref ty) | VectorType::DimensionExpression(_, ref ty) => {
4738 ty.demangle(ctx, scope)?;
4739 }
4740 }
4741
4742 if ctx.pop_inner_if(self) {
4743 self.demangle_as_inner(ctx, scope)?;
4744 }
4745
4746 Ok(())
4747 }
4748 }
4749
4750 impl<'subs, W> DemangleAsInner<'subs, W> for VectorType
4751 where
4752 W: 'subs + DemangleWrite,
4753 {
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4754 fn demangle_as_inner<'prev, 'ctx>(
4755 &'subs self,
4756 ctx: &'ctx mut DemangleContext<'subs, W>,
4757 scope: Option<ArgScopeStack<'prev, 'subs>>,
4758 ) -> fmt::Result {
4759 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4760
4761 match *self {
4762 VectorType::DimensionNumber(n, _) => {
4763 write!(ctx, " __vector({})", n)?;
4764 }
4765 VectorType::DimensionExpression(ref expr, _) => {
4766 write!(ctx, " __vector(")?;
4767 expr.demangle(ctx, scope)?;
4768 write!(ctx, ")")?;
4769 }
4770 }
4771
4772 Ok(())
4773 }
4774 }
4775
4776 /// The `<pointer-to-member-type>` production.
4777 ///
4778 /// ```text
4779 /// <pointer-to-member-type> ::= M <class type> <member type>
4780 /// ```
4781 #[derive(Clone, Debug, PartialEq, Eq)]
4782 pub struct PointerToMemberType(TypeHandle, TypeHandle);
4783
4784 impl Parse for PointerToMemberType {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(PointerToMemberType, IndexStr<'b>)>4785 fn parse<'a, 'b>(
4786 ctx: &'a ParseContext,
4787 subs: &'a mut SubstitutionTable,
4788 input: IndexStr<'b>,
4789 ) -> Result<(PointerToMemberType, IndexStr<'b>)> {
4790 try_begin_parse!("PointerToMemberType", ctx, input);
4791
4792 let tail = consume(b"M", input)?;
4793 let (ty1, tail) = TypeHandle::parse(ctx, subs, tail)?;
4794 let (ty2, tail) = TypeHandle::parse(ctx, subs, tail)?;
4795 Ok((PointerToMemberType(ty1, ty2), tail))
4796 }
4797 }
4798
4799 impl<'subs, W> Demangle<'subs, W> for PointerToMemberType
4800 where
4801 W: 'subs + DemangleWrite,
4802 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4803 fn demangle<'prev, 'ctx>(
4804 &'subs self,
4805 ctx: &'ctx mut DemangleContext<'subs, W>,
4806 scope: Option<ArgScopeStack<'prev, 'subs>>,
4807 ) -> fmt::Result {
4808 let ctx = try_begin_demangle!(self, ctx, scope);
4809
4810 ctx.push_inner(self);
4811 self.1.demangle(ctx, scope)?;
4812 if ctx.pop_inner_if(self) {
4813 self.demangle_as_inner(ctx, scope)?;
4814 }
4815 Ok(())
4816 }
4817 }
4818
4819 impl<'subs, W> DemangleAsInner<'subs, W> for PointerToMemberType
4820 where
4821 W: 'subs + DemangleWrite,
4822 {
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4823 fn demangle_as_inner<'prev, 'ctx>(
4824 &'subs self,
4825 ctx: &'ctx mut DemangleContext<'subs, W>,
4826 scope: Option<ArgScopeStack<'prev, 'subs>>,
4827 ) -> fmt::Result {
4828 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4829
4830 if ctx.last_char_written != Some('(') {
4831 ctx.ensure_space()?;
4832 }
4833
4834 self.0.demangle(ctx, scope)?;
4835 write!(ctx, "::*")?;
4836 Ok(())
4837 }
4838
downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType>4839 fn downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType> {
4840 Some(self)
4841 }
4842 }
4843
4844 /// The `<template-param>` production.
4845 ///
4846 /// ```text
4847 /// <template-param> ::= T_ # first template parameter
4848 /// ::= T <parameter-2 non-negative number> _
4849 /// ```
4850 #[derive(Clone, Debug, PartialEq, Eq)]
4851 pub struct TemplateParam(usize);
4852
4853 impl Parse for TemplateParam {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(TemplateParam, IndexStr<'b>)>4854 fn parse<'a, 'b>(
4855 ctx: &'a ParseContext,
4856 _subs: &'a mut SubstitutionTable,
4857 input: IndexStr<'b>,
4858 ) -> Result<(TemplateParam, IndexStr<'b>)> {
4859 try_begin_parse!("TemplateParam", ctx, input);
4860
4861 let input = consume(b"T", input)?;
4862 let (number, input) = match parse_number(10, false, input) {
4863 Ok((number, input)) => ((number + 1) as _, input),
4864 Err(_) => (0, input),
4865 };
4866 let input = consume(b"_", input)?;
4867 Ok((TemplateParam(number), input))
4868 }
4869 }
4870
4871 impl<'subs, W> Demangle<'subs, W> for TemplateParam
4872 where
4873 W: 'subs + DemangleWrite,
4874 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4875 fn demangle<'prev, 'ctx>(
4876 &'subs self,
4877 ctx: &'ctx mut DemangleContext<'subs, W>,
4878 scope: Option<ArgScopeStack<'prev, 'subs>>,
4879 ) -> fmt::Result {
4880 let ctx = try_begin_demangle!(self, ctx, scope);
4881
4882 ctx.push_demangle_node(DemangleNodeType::TemplateParam);
4883 let ret = if ctx.is_lambda_arg {
4884 // To match libiberty, template references are converted to `auto`.
4885 write!(ctx, "auto:{}", self.0 + 1)
4886 } else {
4887 let arg = self.resolve(scope)?;
4888 arg.demangle(ctx, scope)
4889 };
4890 ctx.pop_demangle_node();
4891 ret
4892 }
4893 }
4894
4895 impl TemplateParam {
resolve<'subs, 'prev>( &'subs self, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> ::std::result::Result<&'subs TemplateArg, fmt::Error>4896 fn resolve<'subs, 'prev>(
4897 &'subs self,
4898 scope: Option<ArgScopeStack<'prev, 'subs>>,
4899 ) -> ::std::result::Result<&'subs TemplateArg, fmt::Error> {
4900 scope
4901 .get_template_arg(self.0)
4902 .map_err(|e| {
4903 log!("Error obtaining template argument: {}", e);
4904 fmt::Error
4905 })
4906 .map(|v| v.0)
4907 }
4908 }
4909
4910 impl<'a> Hash for &'a TemplateParam {
hash<H>(&self, state: &mut H) where H: Hasher,4911 fn hash<H>(&self, state: &mut H)
4912 where
4913 H: Hasher,
4914 {
4915 let self_ref: &TemplateParam = *self;
4916 let self_ptr = self_ref as *const TemplateParam;
4917 self_ptr.hash(state);
4918 }
4919 }
4920
4921 /// The `<template-template-param>` production.
4922 ///
4923 /// ```text
4924 /// <template-template-param> ::= <template-param>
4925 /// ::= <substitution>
4926 /// ```
4927 #[derive(Clone, Debug, PartialEq, Eq)]
4928 pub struct TemplateTemplateParam(TemplateParam);
4929
4930 define_handle! {
4931 /// A reference to a parsed `TemplateTemplateParam`.
4932 pub enum TemplateTemplateParamHandle
4933 }
4934
4935 impl Parse for TemplateTemplateParamHandle {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(TemplateTemplateParamHandle, IndexStr<'b>)>4936 fn parse<'a, 'b>(
4937 ctx: &'a ParseContext,
4938 subs: &'a mut SubstitutionTable,
4939 input: IndexStr<'b>,
4940 ) -> Result<(TemplateTemplateParamHandle, IndexStr<'b>)> {
4941 try_begin_parse!("TemplateTemplateParamHandle", ctx, input);
4942
4943 if let Ok((sub, tail)) = Substitution::parse(ctx, subs, input) {
4944 match sub {
4945 Substitution::WellKnown(component) => {
4946 return Ok((TemplateTemplateParamHandle::WellKnown(component), tail));
4947 }
4948 Substitution::BackReference(idx) => {
4949 // TODO: should this check if the thing at idx is a
4950 // template-template-param? There could otherwise be ambiguity
4951 // with <type>'s <substitution> form...
4952 return Ok((TemplateTemplateParamHandle::BackReference(idx), tail));
4953 }
4954 }
4955 }
4956
4957 let (param, tail) = TemplateParam::parse(ctx, subs, input)?;
4958 let ttp = TemplateTemplateParam(param);
4959 let ttp = Substitutable::TemplateTemplateParam(ttp);
4960 let idx = subs.insert(ttp);
4961 let handle = TemplateTemplateParamHandle::BackReference(idx);
4962 Ok((handle, tail))
4963 }
4964 }
4965
4966 impl<'subs, W> Demangle<'subs, W> for TemplateTemplateParam
4967 where
4968 W: 'subs + DemangleWrite,
4969 {
4970 #[inline]
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4971 fn demangle<'prev, 'ctx>(
4972 &'subs self,
4973 ctx: &'ctx mut DemangleContext<'subs, W>,
4974 scope: Option<ArgScopeStack<'prev, 'subs>>,
4975 ) -> fmt::Result {
4976 let ctx = try_begin_demangle!(self, ctx, scope);
4977
4978 self.0.demangle(ctx, scope)
4979 }
4980 }
4981
4982 /// The <function-param> production.
4983 ///
4984 /// ```text
4985 /// <function-param> ::= fp <top-level CV-qualifiers> _
4986 /// # L == 0, first parameter
4987 /// ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _
4988 /// # L == 0, second and later parameters
4989 /// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _
4990 /// # L > 0, first parameter
4991 /// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> <parameter-2 non-negative number> _
4992 /// # L > 0, second and later parameters
4993 /// ```
4994 #[derive(Clone, Debug, PartialEq, Eq)]
4995 pub struct FunctionParam(usize, CvQualifiers, Option<usize>);
4996
4997 impl Parse for FunctionParam {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(FunctionParam, IndexStr<'b>)>4998 fn parse<'a, 'b>(
4999 ctx: &'a ParseContext,
5000 subs: &'a mut SubstitutionTable,
5001 input: IndexStr<'b>,
5002 ) -> Result<(FunctionParam, IndexStr<'b>)> {
5003 try_begin_parse!("FunctionParam", ctx, input);
5004
5005 let tail = consume(b"f", input)?;
5006 if tail.is_empty() {
5007 return Err(error::Error::UnexpectedEnd);
5008 }
5009
5010 let (scope, tail) = if let Ok(tail) = consume(b"L", tail) {
5011 parse_number(10, false, tail)?
5012 } else {
5013 (0, tail)
5014 };
5015
5016 let tail = consume(b"p", tail)?;
5017
5018 let (qualifiers, tail) = CvQualifiers::parse(ctx, subs, tail)?;
5019
5020 let (param, tail) = if tail.peek() == Some(b'T') {
5021 (None, consume(b"T", tail)?)
5022 } else if let Ok((num, tail)) = parse_number(10, false, tail) {
5023 (Some(num as usize + 1), consume(b"_", tail)?)
5024 } else {
5025 (Some(0), consume(b"_", tail)?)
5026 };
5027
5028 Ok((FunctionParam(scope as _, qualifiers, param), tail))
5029 }
5030 }
5031
5032 impl<'subs, W> Demangle<'subs, W> for FunctionParam
5033 where
5034 W: 'subs + DemangleWrite,
5035 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result5036 fn demangle<'prev, 'ctx>(
5037 &'subs self,
5038 ctx: &'ctx mut DemangleContext<'subs, W>,
5039 scope: Option<ArgScopeStack<'prev, 'subs>>,
5040 ) -> fmt::Result {
5041 let ctx = try_begin_demangle!(self, ctx, scope);
5042
5043 match self.2 {
5044 None => write!(ctx, "this"),
5045 Some(i) => write!(ctx, "{{parm#{}}}", i + 1),
5046 }
5047 }
5048 }
5049
5050 /// The `<template-args>` production.
5051 ///
5052 /// ```text
5053 /// <template-args> ::= I <template-arg>+ E
5054 /// ```
5055 #[derive(Clone, Debug, PartialEq, Eq)]
5056 pub struct TemplateArgs(Vec<TemplateArg>);
5057
5058 impl Parse for TemplateArgs {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(TemplateArgs, IndexStr<'b>)>5059 fn parse<'a, 'b>(
5060 ctx: &'a ParseContext,
5061 subs: &'a mut SubstitutionTable,
5062 input: IndexStr<'b>,
5063 ) -> Result<(TemplateArgs, IndexStr<'b>)> {
5064 try_begin_parse!("TemplateArgs", ctx, input);
5065
5066 let tail = consume(b"I", input)?;
5067
5068 let (args, tail) = one_or_more::<TemplateArg>(ctx, subs, tail)?;
5069 let tail = consume(b"E", tail)?;
5070 Ok((TemplateArgs(args), tail))
5071 }
5072 }
5073
5074 impl<'subs, W> Demangle<'subs, W> for TemplateArgs
5075 where
5076 W: 'subs + DemangleWrite,
5077 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, mut scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result5078 fn demangle<'prev, 'ctx>(
5079 &'subs self,
5080 ctx: &'ctx mut DemangleContext<'subs, W>,
5081 mut scope: Option<ArgScopeStack<'prev, 'subs>>,
5082 ) -> fmt::Result {
5083 let ctx = try_begin_demangle!(self, ctx, scope);
5084 inner_barrier!(ctx);
5085
5086 if ctx.last_char_written == Some('<') {
5087 write!(ctx, " ")?;
5088 }
5089 write!(ctx, "<")?;
5090 ctx.push_demangle_node(DemangleNodeType::TemplateArgs);
5091 let mut need_comma = false;
5092 for arg_index in 0..self.0.len() {
5093 if need_comma {
5094 write!(ctx, ", ")?;
5095 }
5096 if let Some(ref mut scope) = scope {
5097 scope.in_arg = Some((arg_index, self));
5098 }
5099 self.0[arg_index].demangle(ctx, scope)?;
5100 need_comma = true;
5101 }
5102
5103 // Ensure "> >" because old C++ sucks and libiberty (and its tests)
5104 // supports old C++.
5105 if ctx.last_char_written == Some('>') {
5106 write!(ctx, " ")?;
5107 }
5108 ctx.pop_demangle_node();
5109 write!(ctx, ">")?;
5110 Ok(())
5111 }
5112 }
5113
5114 impl<'subs> ArgScope<'subs, 'subs> for TemplateArgs {
leaf_name(&'subs self) -> Result<LeafName<'subs>>5115 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
5116 Err(error::Error::BadLeafNameReference)
5117 }
5118
get_template_arg(&'subs self, idx: usize) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)>5119 fn get_template_arg(&'subs self, idx: usize) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
5120 self.0.get(idx).ok_or(error::Error::BadTemplateArgReference).map(|v| (v, self))
5121 }
5122
get_function_arg(&'subs self, _: usize) -> Result<&'subs Type>5123 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
5124 Err(error::Error::BadFunctionArgReference)
5125 }
5126 }
5127
5128 /// A <template-arg> production.
5129 ///
5130 /// ```text
5131 /// <template-arg> ::= <type> # type or template
5132 /// ::= X <expression> E # expression
5133 /// ::= <expr-primary> # simple expressions
5134 /// ::= J <template-arg>* E # argument pack
5135 /// ```
5136 #[derive(Clone, Debug, PartialEq, Eq)]
5137 pub enum TemplateArg {
5138 /// A type or template.
5139 Type(TypeHandle),
5140
5141 /// An expression.
5142 Expression(Expression),
5143
5144 /// A simple expression.
5145 SimpleExpression(ExprPrimary),
5146
5147 /// An argument pack.
5148 ArgPack(Vec<TemplateArg>),
5149 }
5150
5151 impl Parse for TemplateArg {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(TemplateArg, IndexStr<'b>)>5152 fn parse<'a, 'b>(
5153 ctx: &'a ParseContext,
5154 subs: &'a mut SubstitutionTable,
5155 input: IndexStr<'b>,
5156 ) -> Result<(TemplateArg, IndexStr<'b>)> {
5157 try_begin_parse!("TemplateArg", ctx, input);
5158
5159 if let Ok(tail) = consume(b"X", input) {
5160 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5161 let tail = consume(b"E", tail)?;
5162 return Ok((TemplateArg::Expression(expr), tail));
5163 }
5164
5165 if let Ok((expr, tail)) = ExprPrimary::parse(ctx, subs, input) {
5166 return Ok((TemplateArg::SimpleExpression(expr), tail));
5167 }
5168
5169 if let Ok((ty, tail)) = TypeHandle::parse(ctx, subs, input) {
5170 return Ok((TemplateArg::Type(ty), tail));
5171 }
5172
5173 let tail = if input.peek() == Some(b'J') {
5174 consume(b"J", input)?
5175 } else {
5176 consume(b"I", input)?
5177 };
5178
5179 let (args, tail) = if tail.peek() == Some(b'E') {
5180 (vec![], tail)
5181 } else {
5182 zero_or_more::<TemplateArg>(ctx, subs, tail)?
5183 };
5184 let tail = consume(b"E", tail)?;
5185 Ok((TemplateArg::ArgPack(args), tail))
5186 }
5187 }
5188
5189 impl<'subs, W> Demangle<'subs, W> for TemplateArg
5190 where
5191 W: 'subs + DemangleWrite,
5192 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result5193 fn demangle<'prev, 'ctx>(
5194 &'subs self,
5195 ctx: &'ctx mut DemangleContext<'subs, W>,
5196 scope: Option<ArgScopeStack<'prev, 'subs>>,
5197 ) -> fmt::Result {
5198 let ctx = try_begin_demangle!(self, ctx, scope);
5199
5200 match *self {
5201 TemplateArg::Type(ref ty) => ty.demangle(ctx, scope),
5202 TemplateArg::Expression(ref expr) => expr.demangle(ctx, scope),
5203 TemplateArg::SimpleExpression(ref expr) => expr.demangle(ctx, scope),
5204 TemplateArg::ArgPack(ref args) => {
5205 ctx.is_template_argument_pack = true;
5206 let mut need_comma = false;
5207 for arg in &args[..] {
5208 if need_comma {
5209 write!(ctx, ", ")?;
5210 }
5211 arg.demangle(ctx, scope)?;
5212 need_comma = true;
5213 }
5214 Ok(())
5215 }
5216 }
5217 }
5218 }
5219
5220 /// In libiberty, Member and DerefMember expressions have special handling.
5221 /// They parse an `UnqualifiedName` (not an `UnscopedName` as the cxxabi docs
5222 /// say) and optionally a `TemplateArgs` if it is present. We can't just parse
5223 /// a `Name` or an `UnscopedTemplateName` here because that allows other inputs
5224 /// that libiberty does not.
5225 #[derive(Clone, Debug, PartialEq, Eq)]
5226 pub struct MemberName(Name);
5227
5228 impl Parse for MemberName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(MemberName, IndexStr<'b>)>5229 fn parse<'a, 'b>(
5230 ctx: &'a ParseContext,
5231 subs: &'a mut SubstitutionTable,
5232 input: IndexStr<'b>,
5233 ) -> Result<(MemberName, IndexStr<'b>)> {
5234 try_begin_parse!("MemberName", ctx, input);
5235
5236 let (name, tail) = UnqualifiedName::parse(ctx, subs, input)?;
5237 let name = UnscopedName::Unqualified(name);
5238 if let Ok((template, tail)) = TemplateArgs::parse(ctx, subs, tail) {
5239 let name = UnscopedTemplateName(name);
5240 // In libiberty, these are unsubstitutable.
5241 let idx = subs.insert_non_substitution(Substitutable::UnscopedTemplateName(name));
5242 let handle = UnscopedTemplateNameHandle::NonSubstitution(NonSubstitution(idx));
5243 Ok((MemberName(Name::UnscopedTemplate(handle, template)), tail))
5244 } else {
5245 Ok((MemberName(Name::Unscoped(name)), tail))
5246 }
5247 }
5248 }
5249
5250
5251 impl<'subs, W> Demangle<'subs, W> for MemberName
5252 where
5253 W: 'subs + DemangleWrite,
5254 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result5255 fn demangle<'prev, 'ctx>(
5256 &'subs self,
5257 ctx: &'ctx mut DemangleContext<'subs, W>,
5258 scope: Option<ArgScopeStack<'prev, 'subs>>,
5259 ) -> fmt::Result {
5260 let ctx = try_begin_demangle!(self, ctx, scope);
5261
5262 let needs_parens = self.0.get_template_args(ctx.subs).is_some();
5263 if needs_parens {
5264 write!(ctx, "(")?;
5265 }
5266
5267 self.0.demangle(ctx, scope)?;
5268
5269 if needs_parens {
5270 write!(ctx, ")")?;
5271 }
5272
5273 Ok(())
5274 }
5275 }
5276
5277 /// The `<expression>` production.
5278 ///
5279 /// ```text
5280 /// <expression> ::= <unary operator-name> <expression>
5281 /// ::= <binary operator-name> <expression> <expression>
5282 /// ::= <ternary operator-name> <expression> <expression> <expression>
5283 /// ::= pp_ <expression> # prefix ++
5284 /// ::= mm_ <expression> # prefix --
5285 /// ::= cl <expression>+ E # expression (expr-list), call
5286 /// ::= cv <type> <expression> # type (expression), conversion with one argument
5287 /// ::= cv <type> _ <expression>* E # type (expr-list), conversion with other than one argument
5288 /// ::= tl <type> <expression>* E # type {expr-list}, conversion with braced-init-list argument
5289 /// ::= il <expression> E # {expr-list}, braced-init-list in any other context
5290 /// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
5291 /// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
5292 /// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
5293 /// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
5294 /// ::= [gs] dl <expression> # delete expression
5295 /// ::= [gs] da <expression> # delete[] expression
5296 /// ::= dc <type> <expression> # dynamic_cast<type> (expression)
5297 /// ::= sc <type> <expression> # static_cast<type> (expression)
5298 /// ::= cc <type> <expression> # const_cast<type> (expression)
5299 /// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
5300 /// ::= ti <type> # typeid (type)
5301 /// ::= te <expression> # typeid (expression)
5302 /// ::= st <type> # sizeof (type)
5303 /// ::= sz <expression> # sizeof (expression)
5304 /// ::= at <type> # alignof (type)
5305 /// ::= az <expression> # alignof (expression)
5306 /// ::= nx <expression> # noexcept (expression)
5307 /// ::= <template-param>
5308 /// ::= <function-param>
5309 /// ::= dt <expression> <unresolved-name> # expr.name
5310 /// ::= pt <expression> <unresolved-name> # expr->name
5311 /// ::= ds <expression> <expression> # expr.*expr
5312 /// ::= sZ <template-param> # sizeof...(T), size of a template parameter pack
5313 /// ::= sZ <function-param> # sizeof...(parameter), size of a function parameter pack
5314 /// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
5315 /// ::= sp <expression> # expression..., pack expansion
5316 /// ::= tw <expression> # throw expression
5317 /// ::= tr # throw with no operand (rethrow)
5318 /// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
5319 /// # freestanding dependent name (e.g., T::x),
5320 /// # objectless nonstatic member reference
5321 /// ::= <expr-primary>
5322 /// ```
5323 #[derive(Clone, Debug, PartialEq, Eq)]
5324 pub enum Expression {
5325 /// A unary operator expression.
5326 Unary(OperatorName, Box<Expression>),
5327
5328 /// A binary operator expression.
5329 Binary(OperatorName, Box<Expression>, Box<Expression>),
5330
5331 /// A ternary operator expression.
5332 Ternary(
5333 OperatorName,
5334 Box<Expression>,
5335 Box<Expression>,
5336 Box<Expression>,
5337 ),
5338
5339 /// A prefix `++`.
5340 PrefixInc(Box<Expression>),
5341
5342 /// A prefix `--`.
5343 PrefixDec(Box<Expression>),
5344
5345 /// A call with functor and arguments.
5346 Call(Box<Expression>, Vec<Expression>),
5347
5348 /// A type conversion with one argument.
5349 ConversionOne(TypeHandle, Box<Expression>),
5350
5351 /// A type conversion with many arguments.
5352 ConversionMany(TypeHandle, Vec<Expression>),
5353
5354 /// A type conversion with many arguments.
5355 ConversionBraced(TypeHandle, Vec<Expression>),
5356
5357 /// A braced init list expression.
5358 BracedInitList(Box<Expression>),
5359
5360 /// The `new` operator.
5361 New(Vec<Expression>, TypeHandle, Option<Initializer>),
5362
5363 /// The global `::new` operator.
5364 GlobalNew(Vec<Expression>, TypeHandle, Option<Initializer>),
5365
5366 /// The `new[]` operator.
5367 NewArray(Vec<Expression>, TypeHandle, Option<Initializer>),
5368
5369 /// The global `::new[]` operator.
5370 GlobalNewArray(Vec<Expression>, TypeHandle, Option<Initializer>),
5371
5372 /// The `delete` operator.
5373 Delete(Box<Expression>),
5374
5375 /// The global `::delete` operator.
5376 GlobalDelete(Box<Expression>),
5377
5378 /// The `delete[]` operator.
5379 DeleteArray(Box<Expression>),
5380
5381 /// The global `::delete[]` operator.
5382 GlobalDeleteArray(Box<Expression>),
5383
5384 /// `dynamic_cast<type> (expression)`
5385 DynamicCast(TypeHandle, Box<Expression>),
5386
5387 /// `static_cast<type> (expression)`
5388 StaticCast(TypeHandle, Box<Expression>),
5389
5390 /// `const_cast<type> (expression)`
5391 ConstCast(TypeHandle, Box<Expression>),
5392
5393 /// `reinterpret_cast<type> (expression)`
5394 ReinterpretCast(TypeHandle, Box<Expression>),
5395
5396 /// `typeid (type)`
5397 TypeidType(TypeHandle),
5398
5399 /// `typeid (expression)`
5400 TypeidExpr(Box<Expression>),
5401
5402 /// `sizeof (type)`
5403 SizeofType(TypeHandle),
5404
5405 /// `sizeof (expression)`
5406 SizeofExpr(Box<Expression>),
5407
5408 /// `alignof (type)`
5409 AlignofType(TypeHandle),
5410
5411 /// `alignof (expression)`
5412 AlignofExpr(Box<Expression>),
5413
5414 /// `noexcept (expression)`
5415 Noexcept(Box<Expression>),
5416
5417 /// A named template parameter.
5418 TemplateParam(TemplateParam),
5419
5420 /// A function parameter.
5421 FunctionParam(FunctionParam),
5422
5423 /// `expr.name`
5424 Member(Box<Expression>, MemberName),
5425
5426 /// `expr->name`
5427 DerefMember(Box<Expression>, MemberName),
5428
5429 /// `expr.*expr`
5430 PointerToMember(Box<Expression>, Box<Expression>),
5431
5432 /// `sizeof...(T)`, size of a template parameter pack.
5433 SizeofTemplatePack(TemplateParam),
5434
5435 /// `sizeof...(parameter)`, size of a function parameter pack.
5436 SizeofFunctionPack(FunctionParam),
5437
5438 /// `sizeof...(T)`, size of a captured template parameter pack from an alias
5439 /// template.
5440 SizeofCapturedTemplatePack(Vec<TemplateArg>),
5441
5442 /// `expression...`, pack expansion.
5443 PackExpansion(Box<Expression>),
5444
5445 /// `throw expression`
5446 Throw(Box<Expression>),
5447
5448 /// `throw` with no operand
5449 Rethrow,
5450
5451 /// `f(p)`, `N::f(p)`, `::f(p)`, freestanding dependent name (e.g., `T::x`),
5452 /// objectless nonstatic member reference.
5453 UnresolvedName(UnresolvedName),
5454
5455 /// An `<expr-primary>` production.
5456 Primary(ExprPrimary),
5457 }
5458
5459 impl Parse for Expression {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Expression, IndexStr<'b>)>5460 fn parse<'a, 'b>(
5461 ctx: &'a ParseContext,
5462 subs: &'a mut SubstitutionTable,
5463 input: IndexStr<'b>,
5464 ) -> Result<(Expression, IndexStr<'b>)> {
5465 try_begin_parse!("Expression", ctx, input);
5466
5467 if let Ok(tail) = consume(b"pp_", input) {
5468 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5469 let expr = Expression::PrefixInc(Box::new(expr));
5470 return Ok((expr, tail));
5471 }
5472
5473 if let Ok(tail) = consume(b"mm_", input) {
5474 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5475 let expr = Expression::PrefixDec(Box::new(expr));
5476 return Ok((expr, tail));
5477 }
5478
5479 if let Some((head, tail)) = input.try_split_at(2) {
5480 match head.as_ref() {
5481 b"cl" => {
5482 let (func, tail) = Expression::parse(ctx, subs, tail)?;
5483 let (args, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5484 let tail = consume(b"E", tail)?;
5485 let expr = Expression::Call(Box::new(func), args);
5486 return Ok((expr, tail));
5487 }
5488 b"cv" => {
5489 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5490 if let Ok(tail) = consume(b"_", tail) {
5491 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5492 let tail = consume(b"E", tail)?;
5493 let expr = Expression::ConversionMany(ty, exprs);
5494 return Ok((expr, tail));
5495 } else {
5496 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5497 let expr = Expression::ConversionOne(ty, Box::new(expr));
5498 return Ok((expr, tail));
5499 }
5500 }
5501 b"tl" => {
5502 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5503 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5504 let expr = Expression::ConversionBraced(ty, exprs);
5505 let tail = consume(b"E", tail)?;
5506 return Ok((expr, tail));
5507 }
5508 b"il" => {
5509 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5510 let tail = consume(b"E", tail)?;
5511 let expr = Expression::BracedInitList(Box::new(expr));
5512 return Ok((expr, tail));
5513 }
5514 b"dc" => {
5515 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5516 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5517 let expr = Expression::DynamicCast(ty, Box::new(expr));
5518 return Ok((expr, tail));
5519 }
5520 b"sc" => {
5521 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5522 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5523 let expr = Expression::StaticCast(ty, Box::new(expr));
5524 return Ok((expr, tail));
5525 }
5526 b"cc" => {
5527 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5528 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5529 let expr = Expression::ConstCast(ty, Box::new(expr));
5530 return Ok((expr, tail));
5531 }
5532 b"rc" => {
5533 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5534 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5535 let expr = Expression::ReinterpretCast(ty, Box::new(expr));
5536 return Ok((expr, tail));
5537 }
5538 b"ti" => {
5539 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5540 let expr = Expression::TypeidType(ty);
5541 return Ok((expr, tail));
5542 }
5543 b"te" => {
5544 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5545 let expr = Expression::TypeidExpr(Box::new(expr));
5546 return Ok((expr, tail));
5547 }
5548 b"st" => {
5549 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5550 let expr = Expression::SizeofType(ty);
5551 return Ok((expr, tail));
5552 }
5553 b"sz" => {
5554 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5555 let expr = Expression::SizeofExpr(Box::new(expr));
5556 return Ok((expr, tail));
5557 }
5558 b"at" => {
5559 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5560 let expr = Expression::AlignofType(ty);
5561 return Ok((expr, tail));
5562 }
5563 b"az" => {
5564 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5565 let expr = Expression::AlignofExpr(Box::new(expr));
5566 return Ok((expr, tail));
5567 }
5568 b"nx" => {
5569 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5570 let expr = Expression::Noexcept(Box::new(expr));
5571 return Ok((expr, tail));
5572 }
5573 b"dt" => {
5574 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5575 let (name, tail) = MemberName::parse(ctx, subs, tail)?;
5576 let expr = Expression::Member(Box::new(expr), name);
5577 return Ok((expr, tail));
5578 }
5579 b"pt" => {
5580 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5581 let (name, tail) = MemberName::parse(ctx, subs, tail)?;
5582 let expr = Expression::DerefMember(Box::new(expr), name);
5583 return Ok((expr, tail));
5584 }
5585 b"ds" => {
5586 let (first, tail) = Expression::parse(ctx, subs, tail)?;
5587 let (second, tail) = Expression::parse(ctx, subs, tail)?;
5588 let expr = Expression::PointerToMember(Box::new(first), Box::new(second));
5589 return Ok((expr, tail));
5590 }
5591 b"sZ" => {
5592 if let Ok((param, tail)) = TemplateParam::parse(ctx, subs, tail) {
5593 let expr = Expression::SizeofTemplatePack(param);
5594 return Ok((expr, tail));
5595 }
5596
5597 let (param, tail) = FunctionParam::parse(ctx, subs, tail)?;
5598 let expr = Expression::SizeofFunctionPack(param);
5599 return Ok((expr, tail));
5600 }
5601 b"sP" => {
5602 let (args, tail) = zero_or_more::<TemplateArg>(ctx, subs, tail)?;
5603 let expr = Expression::SizeofCapturedTemplatePack(args);
5604 let tail = consume(b"E", tail)?;
5605 return Ok((expr, tail));
5606 }
5607 b"sp" => {
5608 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5609 let expr = Expression::PackExpansion(Box::new(expr));
5610 return Ok((expr, tail));
5611 }
5612 b"tw" => {
5613 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5614 let expr = Expression::Throw(Box::new(expr));
5615 return Ok((expr, tail));
5616 }
5617 b"tr" => {
5618 let expr = Expression::Rethrow;
5619 return Ok((expr, tail));
5620 }
5621 b"gs" => {
5622 if let Ok((expr, tail)) = can_be_global(true, ctx, subs, tail) {
5623 return Ok((expr, tail));
5624 }
5625 }
5626 _ => {}
5627 }
5628 }
5629
5630 if let Ok((expr, tail)) = can_be_global(false, ctx, subs, input) {
5631 return Ok((expr, tail));
5632 }
5633
5634 if let Ok((param, tail)) = TemplateParam::parse(ctx, subs, input) {
5635 let expr = Expression::TemplateParam(param);
5636 return Ok((expr, tail));
5637 }
5638
5639 if let Ok((param, tail)) = FunctionParam::parse(ctx, subs, input) {
5640 let expr = Expression::FunctionParam(param);
5641 return Ok((expr, tail));
5642 }
5643
5644 if let Ok((name, tail)) = UnresolvedName::parse(ctx, subs, input) {
5645 let expr = Expression::UnresolvedName(name);
5646 return Ok((expr, tail));
5647 }
5648
5649 if let Ok((prim, tail)) = ExprPrimary::parse(ctx, subs, input) {
5650 let expr = Expression::Primary(prim);
5651 return Ok((expr, tail));
5652 }
5653
5654 // "A production for <expression> that directly specifies an operation
5655 // code (e.g., for the -> operator) takes precedence over one that is
5656 // expressed in terms of (unary/binary/ternary) <operator-name>." So try
5657 // and parse unary/binary/ternary expressions last.
5658 let (expr, tail) = OperatorName::parse_from_expr(ctx, subs, input)?;
5659 return Ok((expr, tail));
5660
5661 // Parse the various expressions that can optionally have a leading "gs"
5662 // to indicate that they are in the global namespace. The input is after
5663 // we have already detected consumed the optional "gs" and if we did
5664 // find it, then `is_global` should be true.
5665 fn can_be_global<'a, 'b>(
5666 is_global: bool,
5667 ctx: &'a ParseContext,
5668 subs: &'a mut SubstitutionTable,
5669 input: IndexStr<'b>,
5670 ) -> Result<(Expression, IndexStr<'b>)> {
5671 match input.try_split_at(2) {
5672 None => Err(error::Error::UnexpectedEnd),
5673 Some((head, tail)) => match head.as_ref() {
5674 b"nw" => {
5675 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5676 let tail = consume(b"_", tail)?;
5677 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5678 if let Ok(tail) = consume(b"E", tail) {
5679 let expr = if is_global {
5680 Expression::GlobalNew(exprs, ty, None)
5681 } else {
5682 Expression::New(exprs, ty, None)
5683 };
5684 Ok((expr, tail))
5685 } else {
5686 let (init, tail) = Initializer::parse(ctx, subs, tail)?;
5687 let expr = if is_global {
5688 Expression::GlobalNew(exprs, ty, Some(init))
5689 } else {
5690 Expression::New(exprs, ty, Some(init))
5691 };
5692 Ok((expr, tail))
5693 }
5694 }
5695 b"na" => {
5696 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5697 let tail = consume(b"_", tail)?;
5698 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5699 if let Ok(tail) = consume(b"E", tail) {
5700 let expr = if is_global {
5701 Expression::GlobalNewArray(exprs, ty, None)
5702 } else {
5703 Expression::NewArray(exprs, ty, None)
5704 };
5705 Ok((expr, tail))
5706 } else {
5707 let (init, tail) = Initializer::parse(ctx, subs, tail)?;
5708 let expr = if is_global {
5709 Expression::GlobalNewArray(exprs, ty, Some(init))
5710 } else {
5711 Expression::NewArray(exprs, ty, Some(init))
5712 };
5713 Ok((expr, tail))
5714 }
5715 }
5716 b"dl" => {
5717 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5718 let expr = if is_global {
5719 Expression::GlobalDelete(Box::new(expr))
5720 } else {
5721 Expression::Delete(Box::new(expr))
5722 };
5723 Ok((expr, tail))
5724 }
5725 b"da" => {
5726 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5727 let expr = if is_global {
5728 Expression::GlobalDeleteArray(Box::new(expr))
5729 } else {
5730 Expression::DeleteArray(Box::new(expr))
5731 };
5732 Ok((expr, tail))
5733 }
5734 _ => Err(error::Error::UnexpectedText),
5735 },
5736 }
5737 }
5738 }
5739 }
5740
5741 impl<'subs, W> Demangle<'subs, W> for Expression
5742 where
5743 W: 'subs + DemangleWrite,
5744 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result5745 fn demangle<'prev, 'ctx>(
5746 &'subs self,
5747 ctx: &'ctx mut DemangleContext<'subs, W>,
5748 scope: Option<ArgScopeStack<'prev, 'subs>>,
5749 ) -> fmt::Result {
5750 let ctx = try_begin_demangle!(self, ctx, scope);
5751
5752 match *self {
5753 Expression::Unary(
5754 OperatorName::Simple(ref op),
5755 ref expr
5756 ) if *op == SimpleOperatorName::PostInc || *op == SimpleOperatorName::PostDec => {
5757 expr.demangle_as_subexpr(ctx, scope)?;
5758 op.demangle(ctx, scope)
5759 }
5760 Expression::Unary(ref op, ref expr) => {
5761 op.demangle(ctx, scope)?;
5762 expr.demangle_as_subexpr(ctx, scope)
5763 }
5764 // These need an extra set of parens so that it doesn't close any
5765 // template argument accidentally.
5766 Expression::Binary(
5767 OperatorName::Simple(SimpleOperatorName::Greater),
5768 ref lhs,
5769 ref rhs,
5770 ) => {
5771 write!(ctx, "((")?;
5772 lhs.demangle(ctx, scope)?;
5773 write!(ctx, ")>(")?;
5774 rhs.demangle(ctx, scope)?;
5775 write!(ctx, "))")
5776 }
5777 Expression::Binary(ref op, ref lhs, ref rhs) => {
5778 lhs.demangle_as_subexpr(ctx, scope)?;
5779 op.demangle(ctx, scope)?;
5780 rhs.demangle_as_subexpr(ctx, scope)
5781 }
5782 Expression::Ternary(
5783 OperatorName::Simple(SimpleOperatorName::Question),
5784 ref condition,
5785 ref consequent,
5786 ref alternative,
5787 ) => {
5788 condition.demangle_as_subexpr(ctx, scope)?;
5789 write!(ctx, "?")?;
5790 consequent.demangle_as_subexpr(ctx, scope)?;
5791 write!(ctx, " : ")?;
5792 alternative.demangle_as_subexpr(ctx, scope)
5793 }
5794 Expression::Ternary(ref op, ref e1, ref e2, ref e3) => {
5795 // Nonsensical ternary operator? Just print it like a function call,
5796 // I suppose...
5797 //
5798 // TODO: should we detect and reject this during parsing?
5799 op.demangle(ctx, scope)?;
5800 write!(ctx, "(")?;
5801 e1.demangle(ctx, scope)?;
5802 write!(ctx, ", ")?;
5803 e2.demangle(ctx, scope)?;
5804 write!(ctx, ", ")?;
5805 e3.demangle(ctx, scope)?;
5806 write!(ctx, ")")?;
5807 Ok(())
5808 }
5809 Expression::PrefixInc(ref expr) => {
5810 write!(ctx, "++")?;
5811 expr.demangle(ctx, scope)
5812 }
5813 Expression::PrefixDec(ref expr) => {
5814 write!(ctx, "--")?;
5815 expr.demangle(ctx, scope)
5816 }
5817 Expression::Call(ref functor_expr, ref args) => {
5818 functor_expr.demangle_as_subexpr(ctx, scope)?;
5819 write!(ctx, "(")?;
5820 let mut need_comma = false;
5821 for arg in args {
5822 if need_comma {
5823 write!(ctx, ", ")?;
5824 }
5825 arg.demangle(ctx, scope)?;
5826 need_comma = true;
5827 }
5828 write!(ctx, ")")?;
5829 Ok(())
5830 }
5831 Expression::ConversionOne(ref ty, ref expr) => {
5832 write!(ctx, "(")?;
5833 ty.demangle(ctx, scope)?;
5834 write!(ctx, ")(")?;
5835 expr.demangle(ctx, scope)?;
5836 write!(ctx, ")")?;
5837 Ok(())
5838 }
5839 Expression::ConversionMany(ref ty, ref exprs) => {
5840 ty.demangle(ctx, scope)?;
5841 write!(ctx, "(")?;
5842 let mut need_comma = false;
5843 for expr in exprs {
5844 if need_comma {
5845 write!(ctx, ", ")?;
5846 }
5847 expr.demangle(ctx, scope)?;
5848 need_comma = true;
5849 }
5850 write!(ctx, ")")?;
5851 Ok(())
5852 }
5853 Expression::ConversionBraced(ref ty, ref exprs) => {
5854 ty.demangle(ctx, scope)?;
5855 write!(ctx, "{{")?;
5856 let mut need_comma = false;
5857 for expr in exprs {
5858 if need_comma {
5859 write!(ctx, ", ")?;
5860 }
5861 expr.demangle(ctx, scope)?;
5862 need_comma = true;
5863 }
5864 write!(ctx, "}}")?;
5865 Ok(())
5866 }
5867 Expression::BracedInitList(ref expr) => {
5868 write!(ctx, "{{")?;
5869 expr.demangle(ctx, scope)?;
5870 write!(ctx, "}}")?;
5871 Ok(())
5872 }
5873 // TODO: factor out all this duplication in the `new` variants.
5874 Expression::New(ref exprs, ref ty, ref init) => {
5875 write!(ctx, "new (")?;
5876 let mut need_comma = false;
5877 for expr in exprs {
5878 if need_comma {
5879 write!(ctx, ", ")?;
5880 }
5881 expr.demangle(ctx, scope)?;
5882 need_comma = true;
5883 }
5884 write!(ctx, ") ")?;
5885 ty.demangle(ctx, scope)?;
5886 if let Some(ref init) = *init {
5887 init.demangle(ctx, scope)?;
5888 }
5889 Ok(())
5890 }
5891 Expression::GlobalNew(ref exprs, ref ty, ref init) => {
5892 write!(ctx, "::new (")?;
5893 let mut need_comma = false;
5894 for expr in exprs {
5895 if need_comma {
5896 write!(ctx, ", ")?;
5897 }
5898 expr.demangle(ctx, scope)?;
5899 need_comma = true;
5900 }
5901 write!(ctx, ") ")?;
5902 ty.demangle(ctx, scope)?;
5903 if let Some(ref init) = *init {
5904 init.demangle(ctx, scope)?;
5905 }
5906 Ok(())
5907 }
5908 Expression::NewArray(ref exprs, ref ty, ref init) => {
5909 write!(ctx, "new[] (")?;
5910 let mut need_comma = false;
5911 for expr in exprs {
5912 if need_comma {
5913 write!(ctx, ", ")?;
5914 }
5915 expr.demangle(ctx, scope)?;
5916 need_comma = true;
5917 }
5918 write!(ctx, ") ")?;
5919 ty.demangle(ctx, scope)?;
5920 if let Some(ref init) = *init {
5921 init.demangle(ctx, scope)?;
5922 }
5923 Ok(())
5924 }
5925 Expression::GlobalNewArray(ref exprs, ref ty, ref init) => {
5926 write!(ctx, "::new[] (")?;
5927 let mut need_comma = false;
5928 for expr in exprs {
5929 if need_comma {
5930 write!(ctx, ", ")?;
5931 }
5932 expr.demangle(ctx, scope)?;
5933 need_comma = true;
5934 }
5935 write!(ctx, ") ")?;
5936 ty.demangle(ctx, scope)?;
5937 if let Some(ref init) = *init {
5938 init.demangle(ctx, scope)?;
5939 }
5940 Ok(())
5941 }
5942 Expression::Delete(ref expr) => {
5943 write!(ctx, "delete ")?;
5944 expr.demangle(ctx, scope)
5945 }
5946 Expression::GlobalDelete(ref expr) => {
5947 write!(ctx, "::delete ")?;
5948 expr.demangle(ctx, scope)
5949 }
5950 Expression::DeleteArray(ref expr) => {
5951 write!(ctx, "delete[] ")?;
5952 expr.demangle(ctx, scope)
5953 }
5954 Expression::GlobalDeleteArray(ref expr) => {
5955 write!(ctx, "::delete[] ")?;
5956 expr.demangle(ctx, scope)
5957 }
5958 // TODO: factor out duplicated code from cast variants.
5959 Expression::DynamicCast(ref ty, ref expr) => {
5960 write!(ctx, "dynamic_cast<")?;
5961 ty.demangle(ctx, scope)?;
5962 write!(ctx, ">(")?;
5963 expr.demangle(ctx, scope)?;
5964 write!(ctx, ")")?;
5965 Ok(())
5966 }
5967 Expression::StaticCast(ref ty, ref expr) => {
5968 write!(ctx, "static_cast<")?;
5969 ty.demangle(ctx, scope)?;
5970 write!(ctx, ">(")?;
5971 expr.demangle(ctx, scope)?;
5972 write!(ctx, ")")?;
5973 Ok(())
5974 }
5975 Expression::ConstCast(ref ty, ref expr) => {
5976 write!(ctx, "const_cast<")?;
5977 ty.demangle(ctx, scope)?;
5978 write!(ctx, ">(")?;
5979 expr.demangle(ctx, scope)?;
5980 write!(ctx, ")")?;
5981 Ok(())
5982 }
5983 Expression::ReinterpretCast(ref ty, ref expr) => {
5984 write!(ctx, "reinterpret_cast<")?;
5985 ty.demangle(ctx, scope)?;
5986 write!(ctx, ">(")?;
5987 expr.demangle(ctx, scope)?;
5988 write!(ctx, ")")?;
5989 Ok(())
5990 }
5991 Expression::TypeidType(ref ty) => {
5992 write!(ctx, "typeid (")?;
5993 ty.demangle(ctx, scope)?;
5994 write!(ctx, ")")?;
5995 Ok(())
5996 }
5997 Expression::TypeidExpr(ref expr) => {
5998 write!(ctx, "typeid (")?;
5999 expr.demangle(ctx, scope)?;
6000 write!(ctx, ")")?;
6001 Ok(())
6002 }
6003 Expression::SizeofType(ref ty) => {
6004 write!(ctx, "sizeof (")?;
6005 ty.demangle(ctx, scope)?;
6006 write!(ctx, ")")?;
6007 Ok(())
6008 }
6009 Expression::SizeofExpr(ref expr) => {
6010 write!(ctx, "sizeof (")?;
6011 expr.demangle(ctx, scope)?;
6012 write!(ctx, ")")?;
6013 Ok(())
6014 }
6015 Expression::AlignofType(ref ty) => {
6016 write!(ctx, "alignof (")?;
6017 ty.demangle(ctx, scope)?;
6018 write!(ctx, ")")?;
6019 Ok(())
6020 }
6021 Expression::AlignofExpr(ref expr) => {
6022 write!(ctx, "alignof (")?;
6023 expr.demangle(ctx, scope)?;
6024 write!(ctx, ")")?;
6025 Ok(())
6026 }
6027 Expression::Noexcept(ref expr) => {
6028 write!(ctx, "noexcept (")?;
6029 expr.demangle(ctx, scope)?;
6030 write!(ctx, ")")?;
6031 Ok(())
6032 }
6033 Expression::TemplateParam(ref param) => param.demangle(ctx, scope),
6034 Expression::FunctionParam(ref param) => param.demangle(ctx, scope),
6035 Expression::Member(ref expr, ref name) => {
6036 expr.demangle_as_subexpr(ctx, scope)?;
6037 write!(ctx, ".")?;
6038 name.demangle(ctx, scope)
6039 }
6040 Expression::DerefMember(ref expr, ref name) => {
6041 expr.demangle(ctx, scope)?;
6042 write!(ctx, "->")?;
6043 name.demangle(ctx, scope)
6044 }
6045 Expression::PointerToMember(ref e1, ref e2) => {
6046 e1.demangle(ctx, scope)?;
6047 write!(ctx, ".*")?;
6048 e2.demangle(ctx, scope)
6049 }
6050 Expression::SizeofTemplatePack(ref param) => {
6051 write!(ctx, "sizeof...(")?;
6052 param.demangle(ctx, scope)?;
6053 write!(ctx, ")")?;
6054 Ok(())
6055 }
6056 Expression::SizeofFunctionPack(ref param) => {
6057 write!(ctx, "sizeof...(")?;
6058 param.demangle(ctx, scope)?;
6059 write!(ctx, ")")?;
6060 Ok(())
6061 }
6062 Expression::SizeofCapturedTemplatePack(ref args) => {
6063 write!(ctx, "sizeof...(")?;
6064 let mut need_comma = false;
6065 for arg in args {
6066 if need_comma {
6067 write!(ctx, ", ")?;
6068 }
6069 arg.demangle(ctx, scope)?;
6070 need_comma = true;
6071 }
6072 write!(ctx, ")")?;
6073 Ok(())
6074 }
6075 Expression::PackExpansion(ref pack) => {
6076 pack.demangle_as_subexpr(ctx, scope)?;
6077 write!(ctx, "...")?;
6078 Ok(())
6079 }
6080 Expression::Throw(ref expr) => {
6081 write!(ctx, "throw ")?;
6082 expr.demangle(ctx, scope)
6083 }
6084 Expression::Rethrow => {
6085 write!(ctx, "throw")?;
6086 Ok(())
6087 }
6088 Expression::UnresolvedName(ref name) => name.demangle(ctx, scope),
6089 Expression::Primary(ref expr) => expr.demangle(ctx, scope),
6090 }
6091 }
6092 }
6093
6094 impl Expression {
demangle_as_subexpr<'subs, 'prev, 'ctx, W>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result where W: 'subs + DemangleWrite6095 fn demangle_as_subexpr<'subs, 'prev, 'ctx, W>(
6096 &'subs self,
6097 ctx: &'ctx mut DemangleContext<'subs, W>,
6098 scope: Option<ArgScopeStack<'prev, 'subs>>,
6099 ) -> fmt::Result
6100 where W: 'subs + DemangleWrite
6101 {
6102 let needs_parens = match *self {
6103 Expression::FunctionParam(_) |
6104 Expression::Primary(ExprPrimary::External(_)) => false,
6105 _ => true,
6106 };
6107
6108 if needs_parens {
6109 write!(ctx, "(")?;
6110 }
6111
6112 self.demangle(ctx, scope)?;
6113
6114 if needs_parens {
6115 write!(ctx, ")")?;
6116 }
6117
6118 Ok(())
6119 }
6120 }
6121
6122 /// The `<unresolved-name>` production.
6123 ///
6124 /// ```text
6125 /// <unresolved-name> ::= [gs] <base-unresolved-name>
6126 /// #
6127 /// ::= sr <unresolved-type> <base-unresolved-name>
6128 /// #
6129 /// ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
6130 /// #
6131 /// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
6132 /// # A::x, N::y, A<T>::z; "gs" means leading "::"
6133 /// ```
6134 #[derive(Clone, Debug, PartialEq, Eq)]
6135 pub enum UnresolvedName {
6136 /// `x`
6137 Name(BaseUnresolvedName),
6138
6139 /// `::x`
6140 Global(BaseUnresolvedName),
6141
6142 /// `T::x` or `decltype(p)::x` or `T::N::x` or `decltype(p)::N::x`
6143 Nested1(
6144 UnresolvedTypeHandle,
6145 Vec<UnresolvedQualifierLevel>,
6146 BaseUnresolvedName,
6147 ),
6148
6149 /// `A::x` or `N::y` or `A<T>::z`
6150 Nested2(Vec<UnresolvedQualifierLevel>, BaseUnresolvedName),
6151
6152 /// `::A::x` or `::N::y` or `::A<T>::z`
6153 GlobalNested2(Vec<UnresolvedQualifierLevel>, BaseUnresolvedName),
6154 }
6155
6156 impl Parse for UnresolvedName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(UnresolvedName, IndexStr<'b>)>6157 fn parse<'a, 'b>(
6158 ctx: &'a ParseContext,
6159 subs: &'a mut SubstitutionTable,
6160 input: IndexStr<'b>,
6161 ) -> Result<(UnresolvedName, IndexStr<'b>)> {
6162 try_begin_parse!("UnresolvedName", ctx, input);
6163
6164 if let Ok(tail) = consume(b"gs", input) {
6165 if let Ok((name, tail)) = BaseUnresolvedName::parse(ctx, subs, tail) {
6166 return Ok((UnresolvedName::Global(name), tail));
6167 }
6168
6169 let tail = consume(b"sr", tail)?;
6170 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6171 let tail = consume(b"E", tail)?;
6172 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6173 return Ok((UnresolvedName::GlobalNested2(levels, name), tail));
6174 }
6175
6176 if let Ok((name, tail)) = BaseUnresolvedName::parse(ctx, subs, input) {
6177 return Ok((UnresolvedName::Name(name), tail));
6178 }
6179
6180 let tail = consume(b"sr", input)?;
6181
6182 if tail.peek() == Some(b'N') {
6183 let tail = consume(b"N", tail).unwrap();
6184 let (ty, tail) = UnresolvedTypeHandle::parse(ctx, subs, tail)?;
6185 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6186 let tail = consume(b"E", tail)?;
6187 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6188 return Ok((UnresolvedName::Nested1(ty, levels, name), tail));
6189 }
6190
6191 if let Ok((ty, tail)) = UnresolvedTypeHandle::parse(ctx, subs, tail) {
6192 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6193 return Ok((UnresolvedName::Nested1(ty, vec![], name), tail));
6194 }
6195
6196 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6197 let tail = consume(b"E", tail)?;
6198 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6199 Ok((UnresolvedName::Nested2(levels, name), tail))
6200 }
6201 }
6202
6203 impl<'subs, W> Demangle<'subs, W> for UnresolvedName
6204 where
6205 W: 'subs + DemangleWrite,
6206 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6207 fn demangle<'prev, 'ctx>(
6208 &'subs self,
6209 ctx: &'ctx mut DemangleContext<'subs, W>,
6210 scope: Option<ArgScopeStack<'prev, 'subs>>,
6211 ) -> fmt::Result {
6212 let ctx = try_begin_demangle!(self, ctx, scope);
6213
6214 match *self {
6215 UnresolvedName::Name(ref name) => name.demangle(ctx, scope),
6216 UnresolvedName::Global(ref name) => {
6217 write!(ctx, "::")?;
6218 name.demangle(ctx, scope)
6219 }
6220 UnresolvedName::Nested1(ref ty, ref levels, ref name) => {
6221 ty.demangle(ctx, scope)?;
6222 write!(ctx, "::")?;
6223 for lvl in &levels[..] {
6224 lvl.demangle(ctx, scope)?;
6225 write!(ctx, "::")?;
6226 }
6227 name.demangle(ctx, scope)
6228 }
6229 UnresolvedName::Nested2(ref levels, ref name) => {
6230 for lvl in &levels[..] {
6231 lvl.demangle(ctx, scope)?;
6232 write!(ctx, "::")?;
6233 }
6234 name.demangle(ctx, scope)
6235 }
6236 // `::A::x` or `::N::y` or `::A<T>::z`
6237 UnresolvedName::GlobalNested2(ref levels, ref name) => {
6238 write!(ctx, "::")?;
6239 for lvl in &levels[..] {
6240 lvl.demangle(ctx, scope)?;
6241 write!(ctx, "::")?;
6242 }
6243 name.demangle(ctx, scope)
6244 }
6245 }
6246 }
6247 }
6248
6249 /// The `<unresolved-type>` production.
6250 ///
6251 /// ```text
6252 /// <unresolved-type> ::= <template-param> [ <template-args> ] # T:: or T<X,Y>::
6253 /// ::= <decltype> # decltype(p)::
6254 /// ::= <substitution>
6255 /// ```
6256 #[derive(Clone, Debug, PartialEq, Eq)]
6257 pub enum UnresolvedType {
6258 /// An unresolved template type.
6259 Template(TemplateParam, Option<TemplateArgs>),
6260
6261 /// An unresolved `decltype`.
6262 Decltype(Decltype),
6263 }
6264
6265 define_handle! {
6266 /// A reference to a parsed `<unresolved-type>` production.
6267 pub enum UnresolvedTypeHandle
6268 }
6269
6270 impl Parse for UnresolvedTypeHandle {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(UnresolvedTypeHandle, IndexStr<'b>)>6271 fn parse<'a, 'b>(
6272 ctx: &'a ParseContext,
6273 subs: &'a mut SubstitutionTable,
6274 input: IndexStr<'b>,
6275 ) -> Result<(UnresolvedTypeHandle, IndexStr<'b>)> {
6276 try_begin_parse!("UnresolvedTypeHandle", ctx, input);
6277
6278 if let Ok((param, tail)) = TemplateParam::parse(ctx, subs, input) {
6279 let (args, tail) = if let Ok((args, tail)) = TemplateArgs::parse(ctx, subs, tail) {
6280 (Some(args), tail)
6281 } else {
6282 (None, tail)
6283 };
6284 let ty = UnresolvedType::Template(param, args);
6285 let ty = Substitutable::UnresolvedType(ty);
6286 let idx = subs.insert(ty);
6287 let handle = UnresolvedTypeHandle::BackReference(idx);
6288 return Ok((handle, tail));
6289 }
6290
6291 if let Ok((decltype, tail)) = Decltype::parse(ctx, subs, input) {
6292 let ty = UnresolvedType::Decltype(decltype);
6293 let ty = Substitutable::UnresolvedType(ty);
6294 let idx = subs.insert(ty);
6295 let handle = UnresolvedTypeHandle::BackReference(idx);
6296 return Ok((handle, tail));
6297 }
6298
6299 let (sub, tail) = Substitution::parse(ctx, subs, input)?;
6300 match sub {
6301 Substitution::WellKnown(component) => {
6302 Ok((UnresolvedTypeHandle::WellKnown(component), tail))
6303 }
6304 Substitution::BackReference(idx) => {
6305 // TODO: should this check that the back reference actually
6306 // points to an `<unresolved-type>`?
6307 Ok((UnresolvedTypeHandle::BackReference(idx), tail))
6308 }
6309 }
6310 }
6311 }
6312
6313 impl<'subs, W> Demangle<'subs, W> for UnresolvedType
6314 where
6315 W: 'subs + DemangleWrite,
6316 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6317 fn demangle<'prev, 'ctx>(
6318 &'subs self,
6319 ctx: &'ctx mut DemangleContext<'subs, W>,
6320 scope: Option<ArgScopeStack<'prev, 'subs>>,
6321 ) -> fmt::Result {
6322 let ctx = try_begin_demangle!(self, ctx, scope);
6323
6324 match *self {
6325 UnresolvedType::Decltype(ref dt) => dt.demangle(ctx, scope),
6326 UnresolvedType::Template(ref param, ref args) => {
6327 if let Some(ref args) = *args {
6328 let scope = scope.push(args);
6329 param.demangle(ctx, scope)?;
6330 args.demangle(ctx, scope)?;
6331 } else {
6332 param.demangle(ctx, scope)?;
6333 }
6334 Ok(())
6335 }
6336 }
6337 }
6338 }
6339
6340 /// The `<unresolved-qualifier-level>` production.
6341 ///
6342 /// ```text
6343 /// <unresolved-qualifier-level> ::= <simple-id>
6344 /// ```
6345 #[derive(Clone, Debug, PartialEq, Eq)]
6346 pub struct UnresolvedQualifierLevel(SimpleId);
6347
6348 impl Parse for UnresolvedQualifierLevel {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(UnresolvedQualifierLevel, IndexStr<'b>)>6349 fn parse<'a, 'b>(
6350 ctx: &'a ParseContext,
6351 subs: &'a mut SubstitutionTable,
6352 input: IndexStr<'b>,
6353 ) -> Result<(UnresolvedQualifierLevel, IndexStr<'b>)> {
6354 try_begin_parse!("UnresolvedQualifierLevel", ctx, input);
6355
6356 let (id, tail) = SimpleId::parse(ctx, subs, input)?;
6357 Ok((UnresolvedQualifierLevel(id), tail))
6358 }
6359 }
6360
6361 impl<'subs, W> Demangle<'subs, W> for UnresolvedQualifierLevel
6362 where
6363 W: 'subs + DemangleWrite,
6364 {
6365 #[inline]
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6366 fn demangle<'prev, 'ctx>(
6367 &'subs self,
6368 ctx: &'ctx mut DemangleContext<'subs, W>,
6369 scope: Option<ArgScopeStack<'prev, 'subs>>,
6370 ) -> fmt::Result {
6371 let ctx = try_begin_demangle!(self, ctx, scope);
6372
6373 self.0.demangle(ctx, scope)
6374 }
6375 }
6376
6377 /// The `<simple-id>` production.
6378 ///
6379 /// ```text
6380 /// <simple-id> ::= <source-name> [ <template-args> ]
6381 /// ```
6382 #[derive(Clone, Debug, PartialEq, Eq)]
6383 pub struct SimpleId(SourceName, Option<TemplateArgs>);
6384
6385 impl Parse for SimpleId {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(SimpleId, IndexStr<'b>)>6386 fn parse<'a, 'b>(
6387 ctx: &'a ParseContext,
6388 subs: &'a mut SubstitutionTable,
6389 input: IndexStr<'b>,
6390 ) -> Result<(SimpleId, IndexStr<'b>)> {
6391 try_begin_parse!("SimpleId", ctx, input);
6392
6393 let (name, tail) = SourceName::parse(ctx, subs, input)?;
6394 let (args, tail) = if let Ok((args, tail)) = TemplateArgs::parse(ctx, subs, tail) {
6395 (Some(args), tail)
6396 } else {
6397 (None, tail)
6398 };
6399 Ok((SimpleId(name, args), tail))
6400 }
6401 }
6402
6403 impl<'subs, W> Demangle<'subs, W> for SimpleId
6404 where
6405 W: 'subs + DemangleWrite,
6406 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6407 fn demangle<'prev, 'ctx>(
6408 &'subs self,
6409 ctx: &'ctx mut DemangleContext<'subs, W>,
6410 scope: Option<ArgScopeStack<'prev, 'subs>>,
6411 ) -> fmt::Result {
6412 let ctx = try_begin_demangle!(self, ctx, scope);
6413
6414 self.0.demangle(ctx, scope)?;
6415 if let Some(ref args) = self.1 {
6416 args.demangle(ctx, scope)?;
6417 }
6418 Ok(())
6419 }
6420 }
6421
6422 /// The `<base-unresolved-name>` production.
6423 ///
6424 /// ```text
6425 /// <base-unresolved-name> ::= <simple-id> # unresolved name
6426 /// ::= on <operator-name> # unresolved operator-function-id
6427 /// ::= on <operator-name> <template-args> # unresolved operator template-id
6428 /// ::= dn <destructor-name> # destructor or pseudo-destructor;
6429 /// # e.g. ~X or ~X<N-1>
6430 /// ```
6431 #[derive(Clone, Debug, PartialEq, Eq)]
6432 pub enum BaseUnresolvedName {
6433 /// An unresolved name.
6434 Name(SimpleId),
6435
6436 /// An unresolved function or template function name.
6437 Operator(OperatorName, Option<TemplateArgs>),
6438
6439 /// An unresolved destructor name.
6440 Destructor(DestructorName),
6441 }
6442
6443 impl Parse for BaseUnresolvedName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(BaseUnresolvedName, IndexStr<'b>)>6444 fn parse<'a, 'b>(
6445 ctx: &'a ParseContext,
6446 subs: &'a mut SubstitutionTable,
6447 input: IndexStr<'b>,
6448 ) -> Result<(BaseUnresolvedName, IndexStr<'b>)> {
6449 try_begin_parse!("BaseUnresolvedName", ctx, input);
6450
6451 if let Ok((name, tail)) = SimpleId::parse(ctx, subs, input) {
6452 return Ok((BaseUnresolvedName::Name(name), tail));
6453 }
6454
6455 if let Ok(tail) = consume(b"on", input) {
6456 let (opname, tail) = OperatorName::parse(ctx, subs, tail)?;
6457 let (args, tail) = if let Ok((args, tail)) = TemplateArgs::parse(ctx, subs, tail) {
6458 (Some(args), tail)
6459 } else {
6460 (None, tail)
6461 };
6462 return Ok((BaseUnresolvedName::Operator(opname, args), tail));
6463 }
6464
6465 let tail = consume(b"dn", input)?;
6466 let (name, tail) = DestructorName::parse(ctx, subs, tail)?;
6467 Ok((BaseUnresolvedName::Destructor(name), tail))
6468 }
6469 }
6470
6471 impl<'subs, W> Demangle<'subs, W> for BaseUnresolvedName
6472 where
6473 W: 'subs + DemangleWrite,
6474 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6475 fn demangle<'prev, 'ctx>(
6476 &'subs self,
6477 ctx: &'ctx mut DemangleContext<'subs, W>,
6478 scope: Option<ArgScopeStack<'prev, 'subs>>,
6479 ) -> fmt::Result {
6480 let ctx = try_begin_demangle!(self, ctx, scope);
6481
6482 match *self {
6483 BaseUnresolvedName::Name(ref name) => name.demangle(ctx, scope),
6484 BaseUnresolvedName::Destructor(ref dtor) => dtor.demangle(ctx, scope),
6485 BaseUnresolvedName::Operator(ref op, ref args) => {
6486 op.demangle(ctx, scope)?;
6487 if let Some(ref args) = *args {
6488 args.demangle(ctx, scope)?;
6489 }
6490 Ok(())
6491 }
6492 }
6493 }
6494 }
6495
6496 /// The `<destructor-name>` production.
6497 ///
6498 /// ```text
6499 /// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
6500 /// ::= <simple-id> # e.g., ~A<2*N>
6501 /// ```
6502 #[derive(Clone, Debug, PartialEq, Eq)]
6503 pub enum DestructorName {
6504 /// A destructor for an unresolved type.
6505 Unresolved(UnresolvedTypeHandle),
6506
6507 /// A destructor for a resolved type name.
6508 Name(SimpleId),
6509 }
6510
6511 impl Parse for DestructorName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(DestructorName, IndexStr<'b>)>6512 fn parse<'a, 'b>(
6513 ctx: &'a ParseContext,
6514 subs: &'a mut SubstitutionTable,
6515 input: IndexStr<'b>,
6516 ) -> Result<(DestructorName, IndexStr<'b>)> {
6517 try_begin_parse!("DestructorName", ctx, input);
6518
6519 if let Ok((ty, tail)) = UnresolvedTypeHandle::parse(ctx, subs, input) {
6520 return Ok((DestructorName::Unresolved(ty), tail));
6521 }
6522
6523 let (name, tail) = SimpleId::parse(ctx, subs, input)?;
6524 Ok((DestructorName::Name(name), tail))
6525 }
6526 }
6527
6528 impl<'subs, W> Demangle<'subs, W> for DestructorName
6529 where
6530 W: 'subs + DemangleWrite,
6531 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6532 fn demangle<'prev, 'ctx>(
6533 &'subs self,
6534 ctx: &'ctx mut DemangleContext<'subs, W>,
6535 scope: Option<ArgScopeStack<'prev, 'subs>>,
6536 ) -> fmt::Result {
6537 let ctx = try_begin_demangle!(self, ctx, scope);
6538
6539 write!(ctx, "~")?;
6540 match *self {
6541 DestructorName::Unresolved(ref ty) => ty.demangle(ctx, scope),
6542 DestructorName::Name(ref name) => name.demangle(ctx, scope),
6543 }
6544 }
6545 }
6546
6547 /// The `<expr-primary>` production.
6548 ///
6549 /// ```text
6550 /// <expr-primary> ::= L <type> <value number> E # integer literal
6551 /// ::= L <type> <value float> E # floating literal
6552 /// ::= L <string type> E # string literal
6553 /// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
6554 /// ::= L <pointer type> 0 E # null pointer template argument
6555 /// ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
6556 /// ::= L <mangled-name> E # external name
6557 /// ```
6558 #[derive(Clone, Debug, PartialEq, Eq)]
6559 pub enum ExprPrimary {
6560 /// A type literal.
6561 Literal(TypeHandle, usize, usize),
6562
6563 /// An external name.
6564 External(MangledName),
6565 }
6566
6567 impl Parse for ExprPrimary {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(ExprPrimary, IndexStr<'b>)>6568 fn parse<'a, 'b>(
6569 ctx: &'a ParseContext,
6570 subs: &'a mut SubstitutionTable,
6571 input: IndexStr<'b>,
6572 ) -> Result<(ExprPrimary, IndexStr<'b>)> {
6573 try_begin_parse!("ExprPrimary", ctx, input);
6574
6575 let tail = consume(b"L", input)?;
6576
6577 if let Ok((ty, tail)) = TypeHandle::parse(ctx, subs, tail) {
6578 let start = tail.index();
6579 let num_bytes_in_literal = tail.as_ref().iter().take_while(|&&c| c != b'E').count();
6580 let tail = tail.range_from(num_bytes_in_literal..);
6581 let end = tail.index();
6582 let tail = consume(b"E", tail)?;
6583 let expr = ExprPrimary::Literal(ty, start, end);
6584 return Ok((expr, tail));
6585 }
6586
6587 let (name, tail) = MangledName::parse(ctx, subs, tail)?;
6588 let tail = consume(b"E", tail)?;
6589 let expr = ExprPrimary::External(name);
6590 Ok((expr, tail))
6591 }
6592 }
6593
6594 impl<'subs, W> Demangle<'subs, W> for ExprPrimary
6595 where
6596 W: 'subs + DemangleWrite,
6597 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6598 fn demangle<'prev, 'ctx>(
6599 &'subs self,
6600 ctx: &'ctx mut DemangleContext<'subs, W>,
6601 scope: Option<ArgScopeStack<'prev, 'subs>>,
6602 ) -> fmt::Result {
6603 let ctx = try_begin_demangle!(self, ctx, scope);
6604
6605 fn write_literal<W>(
6606 ctx: &mut DemangleContext<W>,
6607 start: usize,
6608 end: usize,
6609 ) -> fmt::Result
6610 where
6611 W: DemangleWrite,
6612 {
6613 debug_assert!(start <= end);
6614 let start = if start < end && ctx.input[start] == b'n' {
6615 write!(ctx, "-")?;
6616 start + 1
6617 } else {
6618 start
6619 };
6620 let s = ::std::str::from_utf8(&ctx.input[start..end]).map_err(|e| {
6621 log!("Error writing literal: {}", e);
6622 fmt::Error
6623 })?;
6624 ctx.write_str(s)
6625 }
6626
6627 match *self {
6628 ExprPrimary::External(ref name) => {
6629 let saved_show_params = ctx.show_params;
6630 ctx.show_params = true;
6631 let ret = name.demangle(ctx, scope);
6632 ctx.show_params = saved_show_params;
6633 ret
6634 }
6635 ExprPrimary::Literal(
6636 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Bool)),
6637 start,
6638 end,
6639 ) => match &ctx.input[start..end] {
6640 b"0" => write!(ctx, "false"),
6641 b"1" => write!(ctx, "true"),
6642 _ => {
6643 write!(ctx, "(bool)")?;
6644 write_literal(ctx, start, end)
6645 }
6646 },
6647 ExprPrimary::Literal(
6648 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Nullptr)),
6649 _,
6650 _,
6651 ) => write!(ctx, "nullptr"),
6652 ExprPrimary::Literal(
6653 ref ty @ TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Double)),
6654 start,
6655 end,
6656 )
6657 | ExprPrimary::Literal(
6658 ref ty @ TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Float)),
6659 start,
6660 end,
6661 ) => {
6662 write!(ctx, "(")?;
6663 ty.demangle(ctx, scope)?;
6664 let start = if start < end && ctx.input[start] == b'n' {
6665 write!(ctx, ")-[")?;
6666 start + 1
6667 } else {
6668 write!(ctx, ")[")?;
6669 start
6670 };
6671 let s = ::std::str::from_utf8(&ctx.input[start..end]).map_err(|e| {
6672 log!("Error writing literal: {}", e);
6673 fmt::Error
6674 })?;
6675 ctx.write_str(s)?;
6676 write!(ctx, "]")
6677 }
6678 ExprPrimary::Literal(
6679 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int)),
6680 start,
6681 end,
6682 ) => write_literal(ctx, start, end),
6683 ExprPrimary::Literal(ref ty, start, end) => {
6684 write!(ctx, "(")?;
6685 ty.demangle(ctx, scope)?;
6686 write!(ctx, ")")?;
6687 write_literal(ctx, start, end)
6688 }
6689 }
6690 }
6691 }
6692
6693 /// The `<initializer>` production.
6694 ///
6695 /// ```text
6696 /// <initializer> ::= pi <expression>* E # parenthesized initialization
6697 /// ```
6698 #[derive(Clone, Debug, PartialEq, Eq)]
6699 pub struct Initializer(Vec<Expression>);
6700
6701 impl Parse for Initializer {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Initializer, IndexStr<'b>)>6702 fn parse<'a, 'b>(
6703 ctx: &'a ParseContext,
6704 subs: &'a mut SubstitutionTable,
6705 input: IndexStr<'b>,
6706 ) -> Result<(Initializer, IndexStr<'b>)> {
6707 try_begin_parse!("Initializer", ctx, input);
6708
6709 let tail = consume(b"pi", input)?;
6710 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
6711 let tail = consume(b"E", tail)?;
6712 Ok((Initializer(exprs), tail))
6713 }
6714 }
6715
6716 impl<'subs, W> Demangle<'subs, W> for Initializer
6717 where
6718 W: 'subs + DemangleWrite,
6719 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6720 fn demangle<'prev, 'ctx>(
6721 &'subs self,
6722 ctx: &'ctx mut DemangleContext<'subs, W>,
6723 scope: Option<ArgScopeStack<'prev, 'subs>>,
6724 ) -> fmt::Result {
6725 let ctx = try_begin_demangle!(self, ctx, scope);
6726
6727 write!(ctx, "(")?;
6728 let mut need_comma = false;
6729 for expr in &self.0 {
6730 if need_comma {
6731 write!(ctx, ", ")?;
6732 }
6733 expr.demangle(ctx, scope)?;
6734 need_comma = true;
6735 }
6736 write!(ctx, ")")?;
6737 Ok(())
6738 }
6739 }
6740
6741 /// The `<local-name>` production.
6742 ///
6743 /// ```text
6744 /// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
6745 /// := Z <function encoding> E s [<discriminator>]
6746 /// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
6747 /// ```
6748 #[derive(Clone, Debug, PartialEq, Eq)]
6749 pub enum LocalName {
6750 /// The mangling of the enclosing function, the mangling of the entity
6751 /// relative to the function, and an optional discriminator.
6752 Relative(Box<Encoding>, Option<Box<Name>>, Option<Discriminator>),
6753
6754 /// A default argument in a class definition.
6755 Default(Box<Encoding>, Option<usize>, Box<Name>),
6756 }
6757
6758 impl Parse for LocalName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(LocalName, IndexStr<'b>)>6759 fn parse<'a, 'b>(
6760 ctx: &'a ParseContext,
6761 subs: &'a mut SubstitutionTable,
6762 input: IndexStr<'b>,
6763 ) -> Result<(LocalName, IndexStr<'b>)> {
6764 try_begin_parse!("LocalName", ctx, input);
6765
6766 let tail = consume(b"Z", input)?;
6767 let (encoding, tail) = Encoding::parse(ctx, subs, tail)?;
6768 let tail = consume(b"E", tail)?;
6769
6770 if let Ok(tail) = consume(b"s", tail) {
6771 let (disc, tail) = if let Ok((disc, tail)) = Discriminator::parse(ctx, subs, tail) {
6772 (Some(disc), tail)
6773 } else {
6774 (None, tail)
6775 };
6776 return Ok((LocalName::Relative(Box::new(encoding), None, disc), tail));
6777 }
6778
6779 if let Ok(tail) = consume(b"d", tail) {
6780 let (param, tail) = if let Ok((num, tail)) = Number::parse(ctx, subs, tail) {
6781 (Some(num as _), tail)
6782 } else {
6783 (None, tail)
6784 };
6785 let tail = consume(b"_", tail)?;
6786 let (name, tail) = Name::parse(ctx, subs, tail)?;
6787 return Ok((
6788 LocalName::Default(Box::new(encoding), param, Box::new(name)),
6789 tail,
6790 ));
6791 }
6792
6793 let (name, tail) = Name::parse(ctx, subs, tail)?;
6794 let (disc, tail) = if let Ok((disc, tail)) = Discriminator::parse(ctx, subs, tail) {
6795 (Some(disc), tail)
6796 } else {
6797 (None, tail)
6798 };
6799
6800 Ok((
6801 LocalName::Relative(Box::new(encoding), Some(Box::new(name)), disc),
6802 tail,
6803 ))
6804 }
6805 }
6806
6807 impl<'subs, W> Demangle<'subs, W> for LocalName
6808 where
6809 W: 'subs + DemangleWrite,
6810 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6811 fn demangle<'prev, 'ctx>(
6812 &'subs self,
6813 ctx: &'ctx mut DemangleContext<'subs, W>,
6814 scope: Option<ArgScopeStack<'prev, 'subs>>,
6815 ) -> fmt::Result {
6816 let ctx = try_begin_demangle!(self, ctx, scope);
6817
6818 let saved_show_params = ctx.show_params;
6819 ctx.show_params = true;
6820 let ret = match *self {
6821 LocalName::Relative(ref encoding, Some(ref name), _) => {
6822 encoding.demangle(ctx, scope)?;
6823 write!(ctx, "::")?;
6824 name.demangle(ctx, scope)
6825 }
6826 LocalName::Relative(ref encoding, None, _) => {
6827 // No name means that this is the symbol for a string literal.
6828 encoding.demangle(ctx, scope)?;
6829 write!(ctx, "::string literal")?;
6830 Ok(())
6831 }
6832 LocalName::Default(ref encoding, _, _) => encoding.demangle(ctx, scope),
6833 };
6834 ctx.show_params = saved_show_params;
6835 ret
6836 }
6837 }
6838
6839 impl GetTemplateArgs for LocalName {
get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>6840 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
6841 match *self {
6842 LocalName::Relative(_, None, _) => None,
6843 LocalName::Relative(_, Some(ref name), _) | LocalName::Default(_, _, ref name) => {
6844 name.get_template_args(subs)
6845 }
6846 }
6847 }
6848 }
6849
6850 impl<'a> GetLeafName<'a> for LocalName {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>6851 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
6852 match *self {
6853 LocalName::Relative(_, None, _) => None,
6854 LocalName::Relative(_, Some(ref name), _) | LocalName::Default(_, _, ref name) => {
6855 name.get_leaf_name(subs)
6856 }
6857 }
6858 }
6859 }
6860
6861 /// The `<discriminator>` production.
6862 ///
6863 /// ```text
6864 /// <discriminator> := _ <non-negative number> # when number < 10
6865 /// := __ <non-negative number> _ # when number >= 10
6866 /// ```
6867 #[derive(Clone, Debug, PartialEq, Eq)]
6868 pub struct Discriminator(usize);
6869
6870 impl Parse for Discriminator {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Discriminator, IndexStr<'b>)>6871 fn parse<'a, 'b>(
6872 ctx: &'a ParseContext,
6873 _subs: &'a mut SubstitutionTable,
6874 input: IndexStr<'b>,
6875 ) -> Result<(Discriminator, IndexStr<'b>)> {
6876 try_begin_parse!("Discriminator", ctx, input);
6877
6878 let tail = consume(b"_", input)?;
6879
6880 if let Ok(tail) = consume(b"_", tail) {
6881 let (num, tail) = parse_number(10, false, tail)?;
6882 debug_assert!(num >= 0);
6883 if num < 10 {
6884 return Err(error::Error::UnexpectedText);
6885 }
6886 let tail = consume(b"_", tail)?;
6887 return Ok((Discriminator(num as _), tail));
6888 }
6889
6890 match tail.try_split_at(1) {
6891 None => Err(error::Error::UnexpectedEnd),
6892 Some((head, tail)) => match head.as_ref()[0] {
6893 b'0' => Ok((Discriminator(0), tail)),
6894 b'1' => Ok((Discriminator(1), tail)),
6895 b'2' => Ok((Discriminator(2), tail)),
6896 b'3' => Ok((Discriminator(3), tail)),
6897 b'4' => Ok((Discriminator(4), tail)),
6898 b'5' => Ok((Discriminator(5), tail)),
6899 b'6' => Ok((Discriminator(6), tail)),
6900 b'7' => Ok((Discriminator(7), tail)),
6901 b'8' => Ok((Discriminator(8), tail)),
6902 b'9' => Ok((Discriminator(9), tail)),
6903 _ => Err(error::Error::UnexpectedText),
6904 },
6905 }
6906 }
6907 }
6908
6909 /// The `<closure-type-name>` production.
6910 ///
6911 /// ```text
6912 /// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
6913 /// ```
6914 #[derive(Clone, Debug, PartialEq, Eq)]
6915 pub struct ClosureTypeName(LambdaSig, Option<usize>);
6916
6917 impl Parse for ClosureTypeName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(ClosureTypeName, IndexStr<'b>)>6918 fn parse<'a, 'b>(
6919 ctx: &'a ParseContext,
6920 subs: &'a mut SubstitutionTable,
6921 input: IndexStr<'b>,
6922 ) -> Result<(ClosureTypeName, IndexStr<'b>)> {
6923 try_begin_parse!("ClosureTypeName", ctx, input);
6924
6925 let tail = consume(b"Ul", input)?;
6926 let (sig, tail) = LambdaSig::parse(ctx, subs, tail)?;
6927 let tail = consume(b"E", tail)?;
6928 let (num, tail) = if let Ok((num, tail)) = parse_number(10, false, tail) {
6929 (Some(num as _), tail)
6930 } else {
6931 (None, tail)
6932 };
6933 let tail = consume(b"_", tail)?;
6934 Ok((ClosureTypeName(sig, num), tail))
6935 }
6936 }
6937
6938 impl<'subs, W> Demangle<'subs, W> for ClosureTypeName
6939 where
6940 W: 'subs + DemangleWrite,
6941 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6942 fn demangle<'prev, 'ctx>(
6943 &'subs self,
6944 ctx: &'ctx mut DemangleContext<'subs, W>,
6945 scope: Option<ArgScopeStack<'prev, 'subs>>,
6946 ) -> fmt::Result {
6947 let ctx = try_begin_demangle!(self, ctx, scope);
6948
6949 write!(ctx, "{{lambda(")?;
6950 self.0.demangle(ctx, scope)?;
6951 write!(ctx, ")#{}}}", self.1.map_or(1, |n| n + 2))?;
6952 Ok(())
6953 }
6954 }
6955
6956 impl<'subs> ArgScope<'subs, 'subs> for ClosureTypeName {
leaf_name(&'subs self) -> Result<LeafName<'subs>>6957 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
6958 Ok(LeafName::Closure(self))
6959 }
6960
get_template_arg(&'subs self, _: usize) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)>6961 fn get_template_arg(&'subs self, _: usize) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
6962 Err(error::Error::BadTemplateArgReference)
6963 }
6964
get_function_arg(&'subs self, _: usize) -> Result<&'subs Type>6965 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
6966 Err(error::Error::BadFunctionArgReference)
6967 }
6968 }
6969
6970 impl<'a> GetLeafName<'a> for ClosureTypeName {
6971 #[inline]
get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>>6972 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
6973 Some(LeafName::Closure(self))
6974 }
6975 }
6976
6977 impl ClosureTypeName {
6978 #[inline]
starts_with(byte: u8, input: &IndexStr) -> bool6979 fn starts_with(byte: u8, input: &IndexStr) -> bool {
6980 byte == b'U' && input.peek_second().map(|b| b == b'l').unwrap_or(false)
6981 }
6982 }
6983
6984 /// The `<lambda-sig>` production.
6985 ///
6986 /// ```text
6987 /// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
6988 /// ```
6989 #[derive(Clone, Debug, PartialEq, Eq)]
6990 pub struct LambdaSig(Vec<TypeHandle>);
6991
6992 impl LambdaSig {
demangle_args<'subs, 'prev, 'ctx, W>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result where W: 'subs + DemangleWrite6993 fn demangle_args<'subs, 'prev, 'ctx, W>(
6994 &'subs self,
6995 ctx: &'ctx mut DemangleContext<'subs, W>,
6996 scope: Option<ArgScopeStack<'prev, 'subs>>,
6997 ) -> fmt::Result
6998 where W: 'subs + DemangleWrite
6999 {
7000 let mut need_comma = false;
7001 for ty in &self.0 {
7002 if need_comma {
7003 write!(ctx, ", ")?;
7004 }
7005 ty.demangle(ctx, scope)?;
7006 need_comma = true;
7007 }
7008 Ok(())
7009 }
7010 }
7011
7012 impl Parse for LambdaSig {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(LambdaSig, IndexStr<'b>)>7013 fn parse<'a, 'b>(
7014 ctx: &'a ParseContext,
7015 subs: &'a mut SubstitutionTable,
7016 input: IndexStr<'b>,
7017 ) -> Result<(LambdaSig, IndexStr<'b>)> {
7018 try_begin_parse!("LambdaSig", ctx, input);
7019
7020 let (types, tail) = if let Ok(tail) = consume(b"v", input) {
7021 (vec![], tail)
7022 } else {
7023 one_or_more::<TypeHandle>(ctx, subs, input)?
7024 };
7025 Ok((LambdaSig(types), tail))
7026 }
7027 }
7028
7029 impl<'subs, W> Demangle<'subs, W> for LambdaSig
7030 where
7031 W: 'subs + DemangleWrite,
7032 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result7033 fn demangle<'prev, 'ctx>(
7034 &'subs self,
7035 ctx: &'ctx mut DemangleContext<'subs, W>,
7036 scope: Option<ArgScopeStack<'prev, 'subs>>,
7037 ) -> fmt::Result {
7038 let ctx = try_begin_demangle!(self, ctx, scope);
7039
7040 ctx.is_lambda_arg = true;
7041 let r = self.demangle_args(ctx, scope);
7042 ctx.is_lambda_arg = false;
7043 r
7044 }
7045 }
7046
7047 /// The `<data-member-prefix>` production.
7048 ///
7049 /// ```text
7050 /// <data-member-prefix> := <member source-name> M
7051 /// ```
7052 #[derive(Clone, Debug, PartialEq, Eq)]
7053 pub struct DataMemberPrefix(SourceName);
7054
7055 impl Parse for DataMemberPrefix {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(DataMemberPrefix, IndexStr<'b>)>7056 fn parse<'a, 'b>(
7057 ctx: &'a ParseContext,
7058 subs: &'a mut SubstitutionTable,
7059 input: IndexStr<'b>,
7060 ) -> Result<(DataMemberPrefix, IndexStr<'b>)> {
7061 try_begin_parse!("DataMemberPrefix", ctx, input);
7062
7063 let (name, tail) = SourceName::parse(ctx, subs, input)?;
7064 let tail = consume(b"M", tail)?;
7065 Ok((DataMemberPrefix(name), tail))
7066 }
7067 }
7068
7069 impl<'a> GetLeafName<'a> for DataMemberPrefix {
7070 #[inline]
get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>>7071 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7072 Some(LeafName::SourceName(&self.0))
7073 }
7074 }
7075
7076 impl DataMemberPrefix {
starts_with(byte: u8) -> bool7077 fn starts_with(byte: u8) -> bool {
7078 SourceName::starts_with(byte)
7079 }
7080 }
7081
7082 impl<'subs, W> Demangle<'subs, W> for DataMemberPrefix
7083 where
7084 W: 'subs + DemangleWrite,
7085 {
7086 #[inline]
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result7087 fn demangle<'prev, 'ctx>(
7088 &'subs self,
7089 ctx: &'ctx mut DemangleContext<'subs, W>,
7090 scope: Option<ArgScopeStack<'prev, 'subs>>,
7091 ) -> fmt::Result {
7092 let ctx = try_begin_demangle!(self, ctx, scope);
7093
7094 ctx.push_demangle_node(DemangleNodeType::DataMemberPrefix);
7095 let ret = self.0.demangle(ctx, scope);
7096 ctx.pop_demangle_node();
7097 ret
7098 }
7099 }
7100
7101 /// The `<substitution>` form: a back-reference to some component we've already
7102 /// parsed.
7103 ///
7104 /// ```text
7105 /// <substitution> ::= S <seq-id> _
7106 /// ::= S_
7107 /// ::= St # ::std::
7108 /// ::= Sa # ::std::allocator
7109 /// ::= Sb # ::std::basic_string
7110 /// ::= Ss # ::std::basic_string < char,
7111 /// ::std::char_traits<char>,
7112 /// ::std::allocator<char> >
7113 /// ::= Si # ::std::basic_istream<char, std::char_traits<char> >
7114 /// ::= So # ::std::basic_ostream<char, std::char_traits<char> >
7115 /// ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
7116 /// ```
7117 #[derive(Clone, Debug, PartialEq, Eq)]
7118 pub enum Substitution {
7119 /// A reference to an entity that already occurred, ie the `S_` and `S
7120 /// <seq-id> _` forms.
7121 BackReference(usize),
7122
7123 /// A well-known substitution component. These are the components that do
7124 /// not appear in the substitution table, but have abbreviations specified
7125 /// directly in the grammar.
7126 WellKnown(WellKnownComponent),
7127 }
7128
7129 impl Parse for Substitution {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Substitution, IndexStr<'b>)>7130 fn parse<'a, 'b>(
7131 ctx: &'a ParseContext,
7132 subs: &'a mut SubstitutionTable,
7133 input: IndexStr<'b>,
7134 ) -> Result<(Substitution, IndexStr<'b>)> {
7135 try_begin_parse!("Substitution", ctx, input);
7136
7137 if let Ok((well_known, tail)) = WellKnownComponent::parse(ctx, subs, input) {
7138 return Ok((Substitution::WellKnown(well_known), tail));
7139 }
7140
7141 let tail = consume(b"S", input)?;
7142 let (idx, tail) = if let Ok((idx, tail)) = SeqId::parse(ctx, subs, tail) {
7143 (idx.0 + 1, tail)
7144 } else {
7145 (0, tail)
7146 };
7147
7148 if !subs.contains(idx) {
7149 return Err(error::Error::BadBackReference);
7150 }
7151
7152 let tail = consume(b"_", tail)?;
7153 log!("Found a reference to @ {}", idx);
7154 Ok((Substitution::BackReference(idx), tail))
7155 }
7156 }
7157
7158 define_vocabulary! {
7159 /// The `<substitution>` variants that are encoded directly in the grammar,
7160 /// rather than as back references to other components in the substitution
7161 /// table.
7162 #[derive(Clone, Debug, PartialEq, Eq)]
7163 pub enum WellKnownComponent {
7164 Std (b"St", "std"),
7165 StdAllocator (b"Sa", "std::allocator"),
7166 StdString1 (b"Sb", "std::basic_string"),
7167 StdString2 (b"Ss", "std::string"),
7168 StdIstream (b"Si", "std::basic_istream<char, std::char_traits<char> >"),
7169 StdOstream (b"So", "std::ostream"),
7170 StdIostream (b"Sd", "std::basic_iostream<char, std::char_traits<char> >")
7171 }
7172 }
7173
7174 impl<'a> GetLeafName<'a> for WellKnownComponent {
get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>>7175 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7176 match *self {
7177 WellKnownComponent::Std => None,
7178 _ => Some(LeafName::WellKnownComponent(self)),
7179 }
7180 }
7181 }
7182
7183 impl<'a> ArgScope<'a, 'a> for WellKnownComponent {
leaf_name(&'a self) -> Result<LeafName<'a>>7184 fn leaf_name(&'a self) -> Result<LeafName<'a>> {
7185 Ok(LeafName::WellKnownComponent(self))
7186 }
7187
get_template_arg(&'a self, _: usize) -> Result<(&'a TemplateArg, &'a TemplateArgs)>7188 fn get_template_arg(&'a self, _: usize) -> Result<(&'a TemplateArg, &'a TemplateArgs)> {
7189 Err(error::Error::BadTemplateArgReference)
7190 }
7191
get_function_arg(&'a self, _: usize) -> Result<&'a Type>7192 fn get_function_arg(&'a self, _: usize) -> Result<&'a Type> {
7193 Err(error::Error::BadFunctionArgReference)
7194 }
7195 }
7196
7197 impl<'subs, W> DemangleAsLeaf<'subs, W> for WellKnownComponent
7198 where
7199 W: 'subs + DemangleWrite,
7200 {
demangle_as_leaf<'me, 'ctx>( &'me self, ctx: &'ctx mut DemangleContext<'subs, W>, ) -> fmt::Result7201 fn demangle_as_leaf<'me, 'ctx>(
7202 &'me self,
7203 ctx: &'ctx mut DemangleContext<'subs, W>,
7204 ) -> fmt::Result {
7205 match *self {
7206 WellKnownComponent::Std => {
7207 panic!("should never treat `WellKnownComponent::Std` as a leaf name")
7208 }
7209 WellKnownComponent::StdAllocator => write!(ctx, "allocator"),
7210 WellKnownComponent::StdString1 => write!(ctx, "basic_string"),
7211 WellKnownComponent::StdString2 => write!(ctx, "string"),
7212 WellKnownComponent::StdIstream => write!(ctx, "basic_istream"),
7213 WellKnownComponent::StdOstream => write!(ctx, "ostream"),
7214 WellKnownComponent::StdIostream => write!(ctx, "basic_iostream"),
7215 }
7216 }
7217 }
7218
7219
7220 /// The `<special-name>` production.
7221 ///
7222 /// The `<special-name>` production is spread in pieces through out the ABI
7223 /// spec, and then there are a bunch of `g++` extensions that have become de
7224 /// facto.
7225 ///
7226 /// ### 5.1.4.1 Virtual Tables and RTTI
7227 ///
7228 /// ```text
7229 /// <special-name> ::= TV <type> # virtual table
7230 /// ::= TT <type> # VTT structure (construction vtable index)
7231 /// ::= TI <type> # typeinfo structure
7232 /// ::= TS <type> # typeinfo name (null-terminated byte string)
7233 /// ```
7234 ///
7235 /// ### 5.1.4.2 Virtual Override Thunks
7236 ///
7237 /// ```text
7238 /// <special-name> ::= T <call-offset> <base encoding>
7239 /// # base is the nominal target function of thunk
7240 ///
7241 /// <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
7242 /// # base is the nominal target function of thunk
7243 /// # first call-offset is 'this' adjustment
7244 /// # second call-offset is result adjustment
7245 /// ```
7246 ///
7247 /// ### 5.1.4.4 Guard Variables
7248 ///
7249 /// ```text
7250 /// <special-name> ::= GV <object name> # Guard variable for one-time initialization
7251 /// # No <type>
7252 /// ```
7253 ///
7254 /// ### 5.1.4.5 Lifetime-Extended Temporaries
7255 ///
7256 /// ```text
7257 /// <special-name> ::= GR <object name> _ # First temporary
7258 /// <special-name> ::= GR <object name> <seq-id> _ # Subsequent temporaries
7259 /// ```
7260 ///
7261 /// ### De Facto Standard Extensions
7262 ///
7263 /// ```text
7264 /// <special-name> ::= TC <type> <number> _ <type> # construction vtable
7265 /// ::= TF <type> # typinfo function
7266 /// ::= TH <name> # TLS initialization function
7267 /// ::= TW <name> # TLS wrapper function
7268 /// ```
7269 #[derive(Clone, Debug, PartialEq, Eq)]
7270 pub enum SpecialName {
7271 /// A virtual table.
7272 VirtualTable(TypeHandle),
7273
7274 /// A VTT structure (construction vtable index).
7275 Vtt(TypeHandle),
7276
7277 /// A typeinfo structure.
7278 Typeinfo(TypeHandle),
7279
7280 /// A typeinfo name (null-terminated byte string).
7281 TypeinfoName(TypeHandle),
7282
7283 /// A virtual override thunk.
7284 VirtualOverrideThunk(CallOffset, Box<Encoding>),
7285
7286 /// A virtual override thunk with a covariant return type.
7287 VirtualOverrideThunkCovariant(CallOffset, CallOffset, Box<Encoding>),
7288
7289 /// An initialization guard for some static storage.
7290 Guard(Name),
7291
7292 /// A temporary used in the initialization of a static storage and promoted
7293 /// to a static lifetime.
7294 GuardTemporary(Name, usize),
7295
7296 /// A construction vtable structure.
7297 ConstructionVtable(TypeHandle, usize, TypeHandle),
7298
7299 /// A typeinfo function.
7300 TypeinfoFunction(TypeHandle),
7301
7302 /// A TLS initialization function.
7303 TlsInit(Name),
7304
7305 /// A TLS wrapper function.
7306 TlsWrapper(Name),
7307 }
7308
7309 impl Parse for SpecialName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(SpecialName, IndexStr<'b>)>7310 fn parse<'a, 'b>(
7311 ctx: &'a ParseContext,
7312 subs: &'a mut SubstitutionTable,
7313 input: IndexStr<'b>,
7314 ) -> Result<(SpecialName, IndexStr<'b>)> {
7315 try_begin_parse!("SpecialName", ctx, input);
7316
7317 let (head, tail) = match input.try_split_at(2) {
7318 None => return Err(error::Error::UnexpectedEnd),
7319 Some((head, tail)) => (head, tail),
7320 };
7321
7322 match head.as_ref() {
7323 b"TV" => {
7324 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7325 Ok((SpecialName::VirtualTable(ty), tail))
7326 }
7327 b"TT" => {
7328 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7329 Ok((SpecialName::Vtt(ty), tail))
7330 }
7331 b"TI" => {
7332 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7333 Ok((SpecialName::Typeinfo(ty), tail))
7334 }
7335 b"TS" => {
7336 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7337 Ok((SpecialName::TypeinfoName(ty), tail))
7338 }
7339 b"Tc" => {
7340 let (first, tail) = CallOffset::parse(ctx, subs, tail)?;
7341 let (second, tail) = CallOffset::parse(ctx, subs, tail)?;
7342 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7343 Ok((
7344 SpecialName::VirtualOverrideThunkCovariant(first, second, Box::new(base)),
7345 tail,
7346 ))
7347 }
7348 b"Th" | b"Tv" => {
7349 // The "h"/"v" is part of the `<call-offset>`, so back up to the
7350 // `input`.
7351 let tail = consume(b"T", input).unwrap();
7352 let (offset, tail) = CallOffset::parse(ctx, subs, tail)?;
7353 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7354 Ok((
7355 SpecialName::VirtualOverrideThunk(offset, Box::new(base)),
7356 tail,
7357 ))
7358 }
7359 b"TC" => {
7360 let (ty1, tail) = TypeHandle::parse(ctx, subs, tail)?;
7361 let (n, tail) = parse_number(10, false, tail)?;
7362 let tail = consume(b"_", tail)?;
7363 let (ty2, tail) = TypeHandle::parse(ctx, subs, tail)?;
7364 Ok((
7365 SpecialName::ConstructionVtable(ty1, n as usize, ty2),
7366 tail,
7367 ))
7368 }
7369 b"TF" => {
7370 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7371 Ok((SpecialName::TypeinfoFunction(ty), tail))
7372 }
7373 b"TH" => {
7374 let (name, tail) = Name::parse(ctx, subs, tail)?;
7375 Ok((SpecialName::TlsInit(name), tail))
7376 }
7377 b"TW" => {
7378 let (name, tail) = Name::parse(ctx, subs, tail)?;
7379 Ok((SpecialName::TlsWrapper(name), tail))
7380 }
7381 b"GV" => {
7382 let (name, tail) = Name::parse(ctx, subs, tail)?;
7383 Ok((SpecialName::Guard(name), tail))
7384 }
7385 b"GR" => {
7386 let (name, tail) = Name::parse(ctx, subs, tail)?;
7387 let (idx, tail) = if let Ok(tail) = consume(b"_", tail) {
7388 (0, tail)
7389 } else {
7390 let (idx, tail) = SeqId::parse(ctx, subs, tail)?;
7391 let tail = consume(b"_", tail)?;
7392 (idx.0 + 1, tail)
7393 };
7394 Ok((SpecialName::GuardTemporary(name, idx), tail))
7395 }
7396 _ => Err(error::Error::UnexpectedText),
7397 }
7398 }
7399 }
7400
7401 impl<'subs, W> Demangle<'subs, W> for SpecialName
7402 where
7403 W: 'subs + DemangleWrite,
7404 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result7405 fn demangle<'prev, 'ctx>(
7406 &'subs self,
7407 ctx: &'ctx mut DemangleContext<'subs, W>,
7408 scope: Option<ArgScopeStack<'prev, 'subs>>,
7409 ) -> fmt::Result {
7410 let ctx = try_begin_demangle!(self, ctx, scope);
7411
7412 match *self {
7413 SpecialName::VirtualTable(ref ty) => {
7414 write!(ctx, "{{vtable(")?;
7415 ctx.push_demangle_node(DemangleNodeType::VirtualTable);
7416 ty.demangle(ctx, scope)?;
7417 ctx.pop_demangle_node();
7418 write!(ctx, ")}}")?;
7419 Ok(())
7420 }
7421 SpecialName::Vtt(ref ty) => {
7422 write!(ctx, "{{vtt(")?;
7423 ty.demangle(ctx, scope)?;
7424 write!(ctx, ")}}")?;
7425 Ok(())
7426 }
7427 SpecialName::Typeinfo(ref ty) => {
7428 write!(ctx, "typeinfo for ")?;
7429 ty.demangle(ctx, scope)
7430 }
7431 SpecialName::TypeinfoName(ref ty) => {
7432 write!(ctx, "typeinfo name for ")?;
7433 ty.demangle(ctx, scope)
7434 }
7435 SpecialName::VirtualOverrideThunk(ref offset, ref encoding) => {
7436 write!(ctx, "{{virtual override thunk(")?;
7437 offset.demangle(ctx, scope)?;
7438 write!(ctx, ", ")?;
7439 encoding.demangle(ctx, scope)?;
7440 write!(ctx, ")}}")?;
7441 Ok(())
7442 }
7443 SpecialName::VirtualOverrideThunkCovariant(
7444 ref this_offset,
7445 ref result_offset,
7446 ref encoding,
7447 ) => {
7448 write!(ctx, "{{virtual override thunk(")?;
7449 this_offset.demangle(ctx, scope)?;
7450 write!(ctx, ", ")?;
7451 result_offset.demangle(ctx, scope)?;
7452 write!(ctx, ", ")?;
7453 encoding.demangle(ctx, scope)?;
7454 write!(ctx, ")}}")?;
7455 Ok(())
7456 }
7457 SpecialName::Guard(ref name) => {
7458 write!(ctx, "guard variable for ")?;
7459 name.demangle(ctx, scope)
7460 }
7461 SpecialName::GuardTemporary(ref name, n) => {
7462 write!(ctx, "reference temporary #{} for ", n)?;
7463 name.demangle(ctx, scope)
7464 }
7465 SpecialName::ConstructionVtable(ref ty1, _, ref ty2) => {
7466 write!(ctx, "construction vtable for ")?;
7467 ty1.demangle(ctx, scope)?;
7468 write!(ctx, "-in-")?;
7469 ty2.demangle(ctx, scope)
7470 }
7471 SpecialName::TypeinfoFunction(ref ty) => {
7472 write!(ctx, "typeinfo fn for ")?;
7473 ty.demangle(ctx, scope)
7474 }
7475 SpecialName::TlsInit(ref name) => {
7476 write!(ctx, "TLS init function for ")?;
7477 name.demangle(ctx, scope)
7478 }
7479 SpecialName::TlsWrapper(ref name) => {
7480 write!(ctx, "TLS wrapper function for ")?;
7481 name.demangle(ctx, scope)
7482 }
7483 }
7484 }
7485 }
7486
7487 /// Expect and consume the given byte str, and return the advanced `IndexStr` if
7488 /// we saw the expectation. Otherwise return an error of kind
7489 /// `error::Error::UnexpectedText` if the input doesn't match, or
7490 /// `error::Error::UnexpectedEnd` if it isn't long enough.
7491 #[inline]
consume<'a>(expected: &[u8], input: IndexStr<'a>) -> Result<IndexStr<'a>>7492 fn consume<'a>(expected: &[u8], input: IndexStr<'a>) -> Result<IndexStr<'a>> {
7493 match input.try_split_at(expected.len()) {
7494 Some((head, tail)) if head == expected => Ok(tail),
7495 Some(_) => Err(error::Error::UnexpectedText),
7496 None => Err(error::Error::UnexpectedEnd),
7497 }
7498 }
7499
one_or_more<'a, 'b, P>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Vec<P>, IndexStr<'b>)> where P: Parse,7500 fn one_or_more<'a, 'b, P>(
7501 ctx: &'a ParseContext,
7502 subs: &'a mut SubstitutionTable,
7503 input: IndexStr<'b>,
7504 ) -> Result<(Vec<P>, IndexStr<'b>)>
7505 where
7506 P: Parse,
7507 {
7508 let (first, mut tail) = P::parse(ctx, subs, input)?;
7509 let mut results = vec![first];
7510 loop {
7511 if let Ok((parsed, tail_tail)) = P::parse(ctx, subs, tail) {
7512 results.push(parsed);
7513 tail = tail_tail;
7514 } else {
7515 return Ok((results, tail));
7516 }
7517 }
7518 }
7519
zero_or_more<'a, 'b, P>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Vec<P>, IndexStr<'b>)> where P: Parse,7520 fn zero_or_more<'a, 'b, P>(
7521 ctx: &'a ParseContext,
7522 subs: &'a mut SubstitutionTable,
7523 input: IndexStr<'b>,
7524 ) -> Result<(Vec<P>, IndexStr<'b>)>
7525 where
7526 P: Parse,
7527 {
7528 let mut tail = input;
7529 let mut results = vec![];
7530 loop {
7531 if let Ok((parsed, tail_tail)) = P::parse(ctx, subs, tail) {
7532 results.push(parsed);
7533 tail = tail_tail;
7534 } else {
7535 return Ok((results, tail));
7536 }
7537 }
7538 }
7539
7540 /// Parse a number with the given `base`. Do not allow negative numbers
7541 /// (prefixed with an 'n' instead of a '-') if `allow_signed` is false.
7542 #[allow(unsafe_code)]
parse_number(base: u32, allow_signed: bool, mut input: IndexStr) -> Result<(isize, IndexStr)>7543 fn parse_number(base: u32, allow_signed: bool, mut input: IndexStr) -> Result<(isize, IndexStr)> {
7544 if input.is_empty() {
7545 return Err(error::Error::UnexpectedEnd);
7546 }
7547
7548 let num_is_negative = if allow_signed && input.as_ref()[0] == b'n' {
7549 input = input.range_from(1..);
7550
7551 if input.is_empty() {
7552 return Err(error::Error::UnexpectedEnd);
7553 }
7554
7555 true
7556 } else {
7557 false
7558 };
7559
7560 let num_numeric = input
7561 .as_ref()
7562 .iter()
7563 .map(|&c| c as char)
7564 .take_while(|c| c.is_digit(base) && (c.is_numeric() || c.is_uppercase()))
7565 .count();
7566 if num_numeric == 0 {
7567 return Err(error::Error::UnexpectedText);
7568 }
7569
7570 let (head, tail) = input.split_at(num_numeric);
7571 let head = head.as_ref();
7572
7573 if num_numeric > 1 && head[0] == b'0' {
7574 // "<number>s appearing in mangled names never have leading zeroes,
7575 // except for the value zero, represented as '0'."
7576 return Err(error::Error::UnexpectedText);
7577 }
7578
7579 let head = unsafe {
7580 // Safe because we know we only have valid numeric chars in this
7581 // slice, which are valid UTF-8.
7582 ::std::str::from_utf8_unchecked(head)
7583 };
7584
7585 let mut number = isize::from_str_radix(head, base).map_err(|_| error::Error::Overflow)?;
7586 if num_is_negative {
7587 number = -number;
7588 }
7589
7590 Ok((number, tail))
7591 }
7592
7593 #[cfg(test)]
7594 mod tests {
7595 use super::{ArrayType, BareFunctionType, BaseUnresolvedName, BuiltinType, CallOffset,
7596 ClassEnumType, ClosureTypeName, CtorDtorName, CvQualifiers, DataMemberPrefix,
7597 Decltype, DestructorName, Discriminator, Encoding, ExprPrimary, Expression,
7598 FunctionParam, FunctionType, GlobalCtorDtor, Identifier, Initializer, LambdaSig,
7599 LocalName, MangledName, MemberName, Name, NestedName, NonSubstitution, Number,
7600 NvOffset, OperatorName, Parse, ParseContext, PointerToMemberType, Prefix,
7601 PrefixHandle, RefQualifier, SeqId, SimpleId, SimpleOperatorName, SourceName,
7602 SpecialName, StandardBuiltinType, Substitution, TaggedName, TemplateArg,
7603 TemplateArgs, TemplateParam, TemplateTemplateParam, TemplateTemplateParamHandle,
7604 Type, TypeHandle, UnnamedTypeName, UnqualifiedName, UnresolvedName,
7605 UnresolvedQualifierLevel, UnresolvedType, UnresolvedTypeHandle, UnscopedName,
7606 UnscopedTemplateName, UnscopedTemplateNameHandle, VOffset, VectorType,
7607 WellKnownComponent};
7608
7609 use string::String;
7610 use boxed::Box;
7611 use error::Error;
7612 use index_str::IndexStr;
7613 use std::fmt::Debug;
7614 use std::iter::FromIterator;
7615 use subs::{Substitutable, SubstitutionTable};
7616
assert_parse_ok<P, S1, S2, I1, I2>( production: &'static str, subs: S1, input: I1, expected: P, expected_tail: I2, expected_new_subs: S2, ) where P: Debug + Parse + PartialEq, S1: AsRef<[Substitutable]>, S2: AsRef<[Substitutable]>, I1: AsRef<[u8]>, I2: AsRef<[u8]>,7617 fn assert_parse_ok<P, S1, S2, I1, I2>(
7618 production: &'static str,
7619 subs: S1,
7620 input: I1,
7621 expected: P,
7622 expected_tail: I2,
7623 expected_new_subs: S2,
7624 ) where
7625 P: Debug + Parse + PartialEq,
7626 S1: AsRef<[Substitutable]>,
7627 S2: AsRef<[Substitutable]>,
7628 I1: AsRef<[u8]>,
7629 I2: AsRef<[u8]>,
7630 {
7631 let ctx = ParseContext::default();
7632 let input = input.as_ref();
7633 let expected_tail = expected_tail.as_ref();
7634
7635 let expected_subs = SubstitutionTable::from_iter(
7636 subs.as_ref()
7637 .iter()
7638 .cloned()
7639 .chain(expected_new_subs.as_ref().iter().cloned()),
7640 );
7641 let mut subs = SubstitutionTable::from_iter(subs.as_ref().iter().cloned());
7642
7643 match P::parse(&ctx, &mut subs, IndexStr::from(input)) {
7644 Err(error) => panic!(
7645 "Parsing {:?} as {} failed: {}",
7646 String::from_utf8_lossy(input),
7647 production,
7648 error
7649 ),
7650 Ok((value, tail)) => {
7651 if value != expected {
7652 panic!(
7653 "Parsing {:?} as {} produced\n\n{:#?}\n\nbut we expected\n\n{:#?}",
7654 String::from_utf8_lossy(input),
7655 production,
7656 value,
7657 expected
7658 );
7659 }
7660 if tail != expected_tail {
7661 panic!(
7662 "Parsing {:?} as {} left a tail of {:?}, expected {:?}",
7663 String::from_utf8_lossy(input),
7664 production,
7665 tail,
7666 String::from_utf8_lossy(expected_tail)
7667 );
7668 }
7669 if subs[..] != expected_subs[..] {
7670 panic!(
7671 "Parsing {:?} as {} produced a substitutions table of\n\n\
7672 {:#?}\n\n\
7673 but we expected\n\n\
7674 {:#?}",
7675 String::from_utf8_lossy(input),
7676 production,
7677 subs,
7678 expected_subs
7679 );
7680 }
7681 }
7682 }
7683
7684 log!("=== assert_parse_ok PASSED ====================================");
7685 }
7686
simple_assert_parse_ok<P, I1, I2>( production: &'static str, input: I1, expected: P, expected_tail: I2, ) where P: Debug + Parse + PartialEq, I1: AsRef<[u8]>, I2: AsRef<[u8]>,7687 fn simple_assert_parse_ok<P, I1, I2>(
7688 production: &'static str,
7689 input: I1,
7690 expected: P,
7691 expected_tail: I2,
7692 ) where
7693 P: Debug + Parse + PartialEq,
7694 I1: AsRef<[u8]>,
7695 I2: AsRef<[u8]>,
7696 {
7697 assert_parse_ok::<P, _, _, _, _>(production, [], input, expected, expected_tail, []);
7698 }
7699
assert_parse_err<P, S, I>(production: &'static str, subs: S, input: I, expected_error: Error) where P: Debug + Parse + PartialEq, S: AsRef<[Substitutable]>, I: AsRef<[u8]>,7700 fn assert_parse_err<P, S, I>(production: &'static str, subs: S, input: I, expected_error: Error)
7701 where
7702 P: Debug + Parse + PartialEq,
7703 S: AsRef<[Substitutable]>,
7704 I: AsRef<[u8]>,
7705 {
7706 let input = input.as_ref();
7707 let ctx = ParseContext::default();
7708 let mut subs = SubstitutionTable::from_iter(subs.as_ref().iter().cloned());
7709
7710 match P::parse(&ctx, &mut subs, IndexStr::from(input)) {
7711 Err(ref error) if *error == expected_error => {}
7712 Err(ref error) => {
7713 panic!(
7714 "Parsing {:?} as {} produced an error of kind {:?}, but we expected kind {:?}",
7715 String::from_utf8_lossy(input),
7716 production,
7717 error,
7718 expected_error
7719 );
7720 }
7721 Ok((value, tail)) => {
7722 panic!(
7723 "Parsing {:?} as {} produced value\
7724 \n\n\
7725 {:#?}\
7726 \n\n\
7727 and tail {:?}, but we expected error kind {:?}",
7728 String::from_utf8_lossy(input),
7729 production,
7730 value,
7731 tail,
7732 expected_error
7733 );
7734 }
7735 }
7736
7737 log!("=== assert_parse_err PASSED ===================================");
7738 }
7739
simple_assert_parse_err<P, I>(production: &'static str, input: I, expected_error: Error) where P: Debug + Parse + PartialEq, I: AsRef<[u8]>,7740 fn simple_assert_parse_err<P, I>(production: &'static str, input: I, expected_error: Error)
7741 where
7742 P: Debug + Parse + PartialEq,
7743 I: AsRef<[u8]>,
7744 {
7745 assert_parse_err::<P, _, _>(production, [], input, expected_error);
7746 }
7747
7748 #[test]
recursion_limit()7749 fn recursion_limit() {
7750 // Build the mangled symbol for the type `*****char` where the "*****"
7751 // is 10,000 pointer indirections. This is a valid type symbol, but
7752 // something that would cause us to blow the stack.
7753 let mut mangled = String::new();
7754 for _ in 0..10_000 {
7755 mangled.push('P');
7756 }
7757 mangled += "c";
7758
7759 simple_assert_parse_err::<TypeHandle, _>("TypeHandle", mangled, Error::TooMuchRecursion);
7760 }
7761
7762 macro_rules! assert_parse {
7763 ( $production:ident {
7764 $( with subs $subs:expr => {
7765 Ok => {
7766 $( $input:expr => {
7767 $expected:expr ,
7768 $expected_tail:expr ,
7769 $expected_new_subs:expr
7770 } )*
7771 }
7772 Err => {
7773 $( $error_input:expr => $error:expr , )*
7774 }
7775 } )*
7776 } ) => {
7777 $( $(
7778 assert_parse_ok::<$production, _, _, _, _>(stringify!($production),
7779 $subs,
7780 $input,
7781 $expected,
7782 $expected_tail,
7783 $expected_new_subs);
7784 )* )*
7785
7786 $( $(
7787 assert_parse_err::<$production, _, _>(stringify!($production),
7788 $subs,
7789 $error_input,
7790 $error);
7791 )* )*
7792 };
7793
7794 ( $production:ident {
7795 Ok => {
7796 $( $input:expr => {
7797 $expected:expr ,
7798 $expected_tail:expr
7799 } )*
7800 }
7801 Err => {
7802 $( $error_input:expr => $error:expr , )*
7803 }
7804 } ) => {
7805 $(
7806 simple_assert_parse_ok::<$production, _, _>(stringify!($production),
7807 $input,
7808 $expected,
7809 $expected_tail);
7810 )*
7811
7812
7813 $(
7814 simple_assert_parse_err::<$production, _>(stringify!($production),
7815 $error_input,
7816 $error);
7817 )*
7818 };
7819 }
7820
7821 #[test]
parse_mangled_name()7822 fn parse_mangled_name() {
7823 assert_parse!(MangledName {
7824 Ok => {
7825 b"_Z3foo..." => {
7826 MangledName::Encoding(
7827 Encoding::Data(
7828 Name::Unscoped(
7829 UnscopedName::Unqualified(
7830 UnqualifiedName::Source(
7831 SourceName(Identifier {
7832 start: 3,
7833 end: 6,
7834 }))))), vec![]),
7835 b"..."
7836 }
7837 b"_GLOBAL__I__Z3foo..." => {
7838 MangledName::GlobalCtorDtor(
7839 GlobalCtorDtor::Ctor(
7840 Box::new(
7841 MangledName::Encoding(
7842 Encoding::Data(
7843 Name::Unscoped(
7844 UnscopedName::Unqualified(
7845 UnqualifiedName::Source(
7846 SourceName(
7847 Identifier {
7848 start: 14,
7849 end: 17,
7850 }))))), vec![])))),
7851 b"..."
7852 }
7853 }
7854 Err => {
7855 b"_Y" => Error::UnexpectedText,
7856 b"_Z" => Error::UnexpectedEnd,
7857 b"_" => Error::UnexpectedEnd,
7858 b"" => Error::UnexpectedEnd,
7859 b"_GLOBAL_" => Error::UnexpectedEnd,
7860 }
7861 });
7862 }
7863
7864 #[test]
parse_encoding()7865 fn parse_encoding() {
7866 assert_parse!(Encoding {
7867 with subs [] => {
7868 Ok => {
7869 b"3fooi..." => {
7870 Encoding::Function(
7871 Name::Unscoped(
7872 UnscopedName::Unqualified(
7873 UnqualifiedName::Source(
7874 SourceName(Identifier {
7875 start: 1,
7876 end: 4,
7877 })))),
7878 BareFunctionType(vec![
7879 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))
7880 ])),
7881 b"...",
7882 []
7883 }
7884 b"3foo..." => {
7885 Encoding::Data(
7886 Name::Unscoped(
7887 UnscopedName::Unqualified(
7888 UnqualifiedName::Source(
7889 SourceName(Identifier {
7890 start: 1,
7891 end: 4,
7892 }))))),
7893 b"...",
7894 []
7895 }
7896 b"GV3abc..." => {
7897 Encoding::Special(
7898 SpecialName::Guard(
7899 Name::Unscoped(
7900 UnscopedName::Unqualified(
7901 UnqualifiedName::Source(
7902 SourceName(Identifier {
7903 start: 3,
7904 end: 6,
7905 })))))),
7906 b"...",
7907 []
7908 }
7909 }
7910 Err => {
7911 b"zzz" => Error::UnexpectedText,
7912 b"" => Error::UnexpectedEnd,
7913 }
7914 }
7915 });
7916 }
7917
7918 #[test]
parse_global_ctor_dtor()7919 fn parse_global_ctor_dtor() {
7920 assert_parse!(GlobalCtorDtor {
7921 Ok => {
7922 b"_I__Z3foo..." => {
7923 GlobalCtorDtor::Ctor(
7924 Box::new(
7925 MangledName::Encoding(
7926 Encoding::Data(
7927 Name::Unscoped(
7928 UnscopedName::Unqualified(
7929 UnqualifiedName::Source(
7930 SourceName(
7931 Identifier {
7932 start: 6,
7933 end: 9,
7934 }))))), vec![]))),
7935 b"..."
7936 }
7937 b".I__Z3foo..." => {
7938 GlobalCtorDtor::Ctor(
7939 Box::new(
7940 MangledName::Encoding(
7941 Encoding::Data(
7942 Name::Unscoped(
7943 UnscopedName::Unqualified(
7944 UnqualifiedName::Source(
7945 SourceName(
7946 Identifier {
7947 start: 6,
7948 end: 9,
7949 }))))), vec![]))),
7950 b"..."
7951 }
7952 b"$I__Z3foo..." => {
7953 GlobalCtorDtor::Ctor(
7954 Box::new(
7955 MangledName::Encoding(
7956 Encoding::Data(
7957 Name::Unscoped(
7958 UnscopedName::Unqualified(
7959 UnqualifiedName::Source(
7960 SourceName(
7961 Identifier {
7962 start: 6,
7963 end: 9,
7964 }))))), vec![]))),
7965 b"..."
7966 }
7967 b"_D__Z3foo..." => {
7968 GlobalCtorDtor::Dtor(
7969 Box::new(
7970 MangledName::Encoding(
7971 Encoding::Data(
7972 Name::Unscoped(
7973 UnscopedName::Unqualified(
7974 UnqualifiedName::Source(
7975 SourceName(
7976 Identifier {
7977 start: 6,
7978 end: 9,
7979 }))))), vec![]))),
7980 b"..."
7981 }
7982 b".D__Z3foo..." => {
7983 GlobalCtorDtor::Dtor(
7984 Box::new(
7985 MangledName::Encoding(
7986 Encoding::Data(
7987 Name::Unscoped(
7988 UnscopedName::Unqualified(
7989 UnqualifiedName::Source(
7990 SourceName(
7991 Identifier {
7992 start: 6,
7993 end: 9,
7994 }))))), vec![]))),
7995 b"..."
7996 }
7997 b"$D__Z3foo..." => {
7998 GlobalCtorDtor::Dtor(
7999 Box::new(
8000 MangledName::Encoding(
8001 Encoding::Data(
8002 Name::Unscoped(
8003 UnscopedName::Unqualified(
8004 UnqualifiedName::Source(
8005 SourceName(
8006 Identifier {
8007 start: 6,
8008 end: 9,
8009 }))))), vec![]))),
8010 b"..."
8011 }
8012 }
8013 Err => {
8014 b"_I" => Error::UnexpectedEnd,
8015 b"_" => Error::UnexpectedEnd,
8016 b"" => Error::UnexpectedEnd,
8017 b"blag" => Error::UnexpectedText,
8018 b"_J" => Error::UnexpectedText,
8019 b"_IJ" => Error::UnexpectedText,
8020 }
8021 });
8022 }
8023
8024 #[test]
parse_name()8025 fn parse_name() {
8026 assert_parse!(Name {
8027 with subs [
8028 Substitutable::Prefix(
8029 Prefix::Unqualified(
8030 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::New)))),
8031 Substitutable::Prefix(
8032 Prefix::Nested(PrefixHandle::BackReference(0),
8033 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::New)))),
8034 ] => {
8035 Ok => {
8036 b"NS0_3abcE..." => {
8037 Name::Nested(NestedName::Unqualified(CvQualifiers::default(),
8038 None,
8039 PrefixHandle::BackReference(1),
8040 UnqualifiedName::Source(SourceName(Identifier {
8041 start: 5,
8042 end: 8,
8043 })))),
8044 b"...",
8045 []
8046 }
8047 b"3abc..." => {
8048 Name::Unscoped(
8049 UnscopedName::Unqualified(
8050 UnqualifiedName::Source(
8051 SourceName(Identifier {
8052 start: 1,
8053 end: 4,
8054 })))),
8055 b"...",
8056 []
8057 }
8058 b"dlIcE..." => {
8059 Name::UnscopedTemplate(
8060 UnscopedTemplateNameHandle::BackReference(2),
8061 TemplateArgs(vec![
8062 TemplateArg::Type(
8063 TypeHandle::Builtin(
8064 BuiltinType::Standard(StandardBuiltinType::Char)))
8065 ])),
8066 b"...",
8067 [
8068 Substitutable::UnscopedTemplateName(
8069 UnscopedTemplateName(
8070 UnscopedName::Unqualified(
8071 UnqualifiedName::Operator(
8072 OperatorName::Simple(
8073 SimpleOperatorName::Delete))))),
8074 ]
8075 }
8076 b"Z3abcEs..." => {
8077 Name::Local(
8078 LocalName::Relative(
8079 Box::new(Encoding::Data(
8080 Name::Unscoped(
8081 UnscopedName::Unqualified(
8082 UnqualifiedName::Source(
8083 SourceName(Identifier {
8084 start: 2,
8085 end: 5,
8086 })))))),
8087 None,
8088 None)),
8089 b"...",
8090 []
8091 }
8092 }
8093 Err => {
8094 b"zzz" => Error::UnexpectedText,
8095 b"" => Error::UnexpectedEnd,
8096 }
8097 }
8098 });
8099 }
8100
8101 #[test]
parse_unscoped_template_name_handle()8102 fn parse_unscoped_template_name_handle() {
8103 assert_parse!(UnscopedTemplateNameHandle {
8104 with subs [
8105 Substitutable::UnscopedTemplateName(
8106 UnscopedTemplateName(
8107 UnscopedName::Unqualified(
8108 UnqualifiedName::Operator(
8109 OperatorName::Simple(
8110 SimpleOperatorName::New))))),
8111 ] => {
8112 Ok => {
8113 b"S_..." => {
8114 UnscopedTemplateNameHandle::BackReference(0),
8115 b"...",
8116 []
8117 }
8118 b"dl..." => {
8119 UnscopedTemplateNameHandle::BackReference(1),
8120 b"...",
8121 [
8122 Substitutable::UnscopedTemplateName(
8123 UnscopedTemplateName(
8124 UnscopedName::Unqualified(
8125 UnqualifiedName::Operator(
8126 OperatorName::Simple(
8127 SimpleOperatorName::Delete)))))
8128 ]
8129 }
8130 }
8131 Err => {
8132 b"zzzz" => Error::UnexpectedText,
8133 b"" => Error::UnexpectedEnd,
8134 }
8135 }
8136 });
8137 }
8138
8139 #[test]
parse_nested_name()8140 fn parse_nested_name() {
8141 // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
8142 // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
8143 assert_parse!(NestedName {
8144 with subs [
8145 Substitutable::Prefix(
8146 Prefix::Unqualified(
8147 UnqualifiedName::Operator(
8148 OperatorName::Simple(
8149 SimpleOperatorName::New)))),
8150 ] => {
8151 Ok => {
8152 b"NKOS_3abcE..." => {
8153 NestedName::Unqualified(
8154 CvQualifiers {
8155 restrict: false,
8156 volatile: false,
8157 const_: true,
8158 },
8159 Some(RefQualifier::RValueRef),
8160 PrefixHandle::BackReference(0),
8161 UnqualifiedName::Source(
8162 SourceName(Identifier {
8163 start: 6,
8164 end: 9,
8165 }))),
8166 b"...",
8167 []
8168 }
8169 b"NOS_3abcE..." => {
8170 NestedName::Unqualified(
8171 CvQualifiers {
8172 restrict: false,
8173 volatile: false,
8174 const_: false,
8175 },
8176 Some(RefQualifier::RValueRef),
8177 PrefixHandle::BackReference(0),
8178 UnqualifiedName::Source(
8179 SourceName(Identifier {
8180 start: 5,
8181 end: 8,
8182 }))),
8183 b"...",
8184 []
8185 }
8186 b"NS_3abcE..." => {
8187 NestedName::Unqualified(
8188 CvQualifiers {
8189 restrict: false,
8190 volatile: false,
8191 const_: false,
8192 },
8193 None,
8194 PrefixHandle::BackReference(0),
8195 UnqualifiedName::Source(
8196 SourceName(Identifier {
8197 start: 4,
8198 end: 7,
8199 }))),
8200 b"...",
8201 []
8202 }
8203 b"NKOS_3abcIJEEE..." => {
8204 NestedName::Template(
8205 CvQualifiers {
8206 restrict: false,
8207 volatile: false,
8208 const_: true,
8209 },
8210 Some(RefQualifier::RValueRef),
8211 PrefixHandle::NonSubstitution(NonSubstitution(0))),
8212 b"...",
8213 [
8214 Substitutable::Prefix(
8215 Prefix::Nested(
8216 PrefixHandle::BackReference(0),
8217 UnqualifiedName::Source(
8218 SourceName(Identifier {
8219 start: 6,
8220 end: 9,
8221 })))),
8222 ]
8223 }
8224 b"NOS_3abcIJEEE..." => {
8225 NestedName::Template(
8226 CvQualifiers {
8227 restrict: false,
8228 volatile: false,
8229 const_: false,
8230 },
8231 Some(RefQualifier::RValueRef),
8232 PrefixHandle::NonSubstitution(NonSubstitution(0))),
8233 b"...",
8234 [
8235 Substitutable::Prefix(
8236 Prefix::Nested(
8237 PrefixHandle::BackReference(0),
8238 UnqualifiedName::Source(
8239 SourceName(Identifier {
8240 start: 5,
8241 end: 8,
8242 })))),
8243 ]
8244 }
8245 b"NS_3abcIJEEE..." => {
8246 NestedName::Template(
8247 CvQualifiers {
8248 restrict: false,
8249 volatile: false,
8250 const_: false,
8251 },
8252 None,
8253 PrefixHandle::NonSubstitution(NonSubstitution(0))),
8254 b"...",
8255 [
8256 Substitutable::Prefix(
8257 Prefix::Nested(
8258 PrefixHandle::BackReference(0),
8259 UnqualifiedName::Source(
8260 SourceName(Identifier {
8261 start: 4,
8262 end: 7,
8263 })))),
8264 ]
8265 }
8266 }
8267 Err => {
8268 // Ends with a prefix that is not a name or template.
8269 b"NS_E..." => Error::UnexpectedText,
8270 b"NS_DttrEE..." => Error::UnexpectedText,
8271
8272 b"zzz" => Error::UnexpectedText,
8273 b"Nzzz" => Error::UnexpectedText,
8274 b"NKzzz" => Error::UnexpectedText,
8275 b"NKOzzz" => Error::UnexpectedText,
8276 b"NKO3abczzz" => Error::UnexpectedText,
8277 b"NKO3abc3abczzz" => Error::UnexpectedText,
8278 b"" => Error::UnexpectedEnd,
8279 b"N" => Error::UnexpectedEnd,
8280 b"NK" => Error::UnexpectedEnd,
8281 b"NKO" => Error::UnexpectedEnd,
8282 b"NKO3abc" => Error::UnexpectedEnd,
8283 b"NKO3abc3abc" => Error::UnexpectedEnd,
8284 }
8285 }
8286 });
8287 }
8288
8289 #[test]
parse_prefix_handle()8290 fn parse_prefix_handle() {
8291 // <prefix> ::= <unqualified-name>
8292 // ::= <prefix> <unqualified-name>
8293 // ::= <template-prefix> <template-args>
8294 // ::= <template-param>
8295 // ::= <decltype>
8296 // ::= <prefix> <data-member-prefix>
8297 // ::= <substitution>
8298 assert_parse!(PrefixHandle {
8299 with subs [
8300 Substitutable::Prefix(
8301 Prefix::Unqualified(
8302 UnqualifiedName::Operator(
8303 OperatorName::Simple(
8304 SimpleOperatorName::New)))),
8305 ] => {
8306 Ok => {
8307 b"3foo..." => {
8308 PrefixHandle::BackReference(1),
8309 b"...",
8310 [
8311 Substitutable::Prefix(
8312 Prefix::Unqualified(
8313 UnqualifiedName::Source(
8314 SourceName(Identifier {
8315 start: 1,
8316 end: 4,
8317 }))))
8318 ]
8319 }
8320 b"3abc3def..." => {
8321 PrefixHandle::BackReference(2),
8322 b"...",
8323 [
8324 Substitutable::Prefix(
8325 Prefix::Unqualified(
8326 UnqualifiedName::Source(
8327 SourceName(Identifier {
8328 start: 1,
8329 end: 4,
8330 })))),
8331 Substitutable::Prefix(
8332 Prefix::Nested(
8333 PrefixHandle::BackReference(1),
8334 UnqualifiedName::Source(
8335 SourceName(Identifier {
8336 start: 5,
8337 end: 8,
8338 })))),
8339 ]
8340 }
8341 b"3fooIJEE..." => {
8342 PrefixHandle::BackReference(2),
8343 b"...",
8344 [
8345 Substitutable::Prefix(
8346 Prefix::Unqualified(
8347 UnqualifiedName::Source(
8348 SourceName(Identifier {
8349 start: 1,
8350 end: 4,
8351 })))),
8352 Substitutable::Prefix(
8353 Prefix::Template(PrefixHandle::BackReference(1),
8354 TemplateArgs(vec![
8355 TemplateArg::ArgPack(vec![]),
8356 ])))
8357 ]
8358 }
8359 b"T_..." => {
8360 PrefixHandle::BackReference(1),
8361 b"...",
8362 [
8363 Substitutable::Prefix(Prefix::TemplateParam(TemplateParam(0))),
8364 ]
8365 }
8366 b"DTtrE..." => {
8367 PrefixHandle::BackReference(1),
8368 b"...",
8369 [
8370 Substitutable::Prefix(
8371 Prefix::Decltype(
8372 Decltype::Expression(Expression::Rethrow))),
8373 ]
8374 }
8375 b"3abc3defM..." => {
8376 PrefixHandle::BackReference(2),
8377 b"...",
8378 [
8379 Substitutable::Prefix(
8380 Prefix::Unqualified(
8381 UnqualifiedName::Source(
8382 SourceName(Identifier {
8383 start: 1,
8384 end: 4,
8385 })))),
8386 Substitutable::Prefix(
8387 Prefix::DataMember(
8388 PrefixHandle::BackReference(1),
8389 DataMemberPrefix(
8390 SourceName(Identifier {
8391 start: 5,
8392 end: 8,
8393 })))),
8394 ]
8395 }
8396 b"S_..." => {
8397 PrefixHandle::BackReference(0),
8398 b"...",
8399 []
8400 }
8401 // The trailing E and <nested-name> case...
8402 b"3abc3defE..." => {
8403 PrefixHandle::NonSubstitution(NonSubstitution(0)),
8404 b"E...",
8405 [
8406 Substitutable::Prefix(
8407 Prefix::Unqualified(
8408 UnqualifiedName::Source(
8409 SourceName(Identifier {
8410 start: 1,
8411 end: 4,
8412 })))),
8413 ]
8414 }
8415 }
8416 Err => {
8417 b"zzz" => Error::UnexpectedText,
8418 b"" => Error::UnexpectedEnd,
8419 }
8420 }
8421 });
8422 }
8423
8424 #[test]
parse_type_handle()8425 fn parse_type_handle() {
8426 assert_parse!(TypeHandle {
8427 with subs [
8428 Substitutable::Type(
8429 Type::PointerTo(
8430 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
8431 ] => {
8432 Ok => {
8433 b"S_..." => {
8434 TypeHandle::BackReference(0),
8435 b"...",
8436 []
8437 }
8438 b"c..." => {
8439 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)),
8440 b"...",
8441 []
8442 }
8443 b"FS_E..." => {
8444 TypeHandle::BackReference(1),
8445 b"...",
8446 [
8447 Substitutable::Type(
8448 Type::Function(FunctionType {
8449 cv_qualifiers: CvQualifiers {
8450 restrict: false,
8451 volatile: false,
8452 const_: false,
8453 },
8454 transaction_safe: false,
8455 extern_c: false,
8456 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
8457 ref_qualifier: None,
8458 })),
8459 ]
8460 }
8461 b"A_S_..." => {
8462 TypeHandle::BackReference(1),
8463 b"...",
8464 [
8465 Substitutable::Type(
8466 Type::Array(ArrayType::NoDimension(TypeHandle::BackReference(0)))),
8467 ]
8468 }
8469 b"MS_S_..." => {
8470 TypeHandle::BackReference(1),
8471 b"...",
8472 [
8473 Substitutable::Type(
8474 Type::PointerToMember(
8475 PointerToMemberType(TypeHandle::BackReference(0),
8476 TypeHandle::BackReference(0)))),
8477 ]
8478 }
8479 b"T_..." => {
8480 TypeHandle::BackReference(1),
8481 b"...",
8482 [
8483 Substitutable::Type(Type::TemplateParam(TemplateParam(0))),
8484 ]
8485 }
8486 b"T_IS_E..." => {
8487 TypeHandle::BackReference(2),
8488 b"...",
8489 [
8490 Substitutable::TemplateTemplateParam(
8491 TemplateTemplateParam(TemplateParam(0))),
8492 Substitutable::Type(
8493 Type::TemplateTemplate(
8494 TemplateTemplateParamHandle::BackReference(1),
8495 TemplateArgs(vec![
8496 TemplateArg::Type(TypeHandle::BackReference(0))
8497 ]))),
8498 ]
8499 }
8500 b"DTtrE..." => {
8501 TypeHandle::BackReference(1),
8502 b"...",
8503 [
8504 Substitutable::Type(
8505 Type::Decltype(Decltype::Expression(Expression::Rethrow))),
8506 ]
8507 }
8508 b"KS_..." => {
8509 TypeHandle::BackReference(1),
8510 b"...",
8511 [
8512 Substitutable::Type(Type::Qualified(CvQualifiers {
8513 restrict: false,
8514 volatile: false,
8515 const_: true,
8516 }, TypeHandle::BackReference(0)))
8517 ]
8518 }
8519 b"PS_..." => {
8520 TypeHandle::BackReference(1),
8521 b"...",
8522 [
8523 Substitutable::Type(Type::PointerTo(TypeHandle::BackReference(0)))
8524 ]
8525 }
8526 b"RS_..." => {
8527 TypeHandle::BackReference(1),
8528 b"...",
8529 [
8530 Substitutable::Type(Type::LvalueRef(TypeHandle::BackReference(0)))
8531 ]
8532 }
8533 b"OS_..." => {
8534 TypeHandle::BackReference(1),
8535 b"...",
8536 [
8537 Substitutable::Type(Type::RvalueRef(TypeHandle::BackReference(0)))
8538 ]
8539 }
8540 b"CS_..." => {
8541 TypeHandle::BackReference(1),
8542 b"...",
8543 [
8544 Substitutable::Type(Type::Complex(TypeHandle::BackReference(0)))
8545 ]
8546 }
8547 b"GS_..." => {
8548 TypeHandle::BackReference(1),
8549 b"...",
8550 [
8551 Substitutable::Type(Type::Imaginary(TypeHandle::BackReference(0)))
8552 ]
8553 }
8554 b"U3abcS_..." => {
8555 TypeHandle::BackReference(1),
8556 b"...",
8557 [
8558 Substitutable::Type(
8559 Type::VendorExtension(
8560 SourceName(Identifier {
8561 start: 2,
8562 end: 5,
8563 }),
8564 None,
8565 TypeHandle::BackReference(0)))
8566 ]
8567 }
8568 b"U3abcIS_ES_..." => {
8569 TypeHandle::BackReference(1),
8570 b"...",
8571 [
8572 Substitutable::Type(
8573 Type::VendorExtension(
8574 SourceName(Identifier {
8575 start: 2,
8576 end: 5,
8577 }),
8578 Some(TemplateArgs(vec![
8579 TemplateArg::Type(TypeHandle::BackReference(0))
8580 ])),
8581 TypeHandle::BackReference(0)))
8582 ]
8583 }
8584 b"DpS_..." => {
8585 TypeHandle::BackReference(1),
8586 b"...",
8587 [
8588 Substitutable::Type(
8589 Type::PackExpansion(TypeHandle::BackReference(0))),
8590 ]
8591 }
8592 b"3abc..." => {
8593 TypeHandle::BackReference(1),
8594 b"...",
8595 [
8596 Substitutable::Type(
8597 Type::ClassEnum(
8598 ClassEnumType::Named(
8599 Name::Unscoped(
8600 UnscopedName::Unqualified(
8601 UnqualifiedName::Source(
8602 SourceName(Identifier {
8603 start: 1,
8604 end: 4,
8605 })))))))
8606 ]
8607 }
8608 }
8609 Err => {
8610 b"P" => Error::UnexpectedEnd,
8611 b"R" => Error::UnexpectedEnd,
8612 b"O" => Error::UnexpectedEnd,
8613 b"C" => Error::UnexpectedEnd,
8614 b"G" => Error::UnexpectedEnd,
8615 b"Dp" => Error::UnexpectedEnd,
8616 b"D" => Error::UnexpectedEnd,
8617 b"P" => Error::UnexpectedEnd,
8618 b"" => Error::UnexpectedEnd,
8619 }
8620 }
8621 });
8622 }
8623
8624 #[test]
parse_function_type()8625 fn parse_function_type() {
8626 assert_parse!(FunctionType {
8627 with subs [
8628 Substitutable::Type(
8629 Type::PointerTo(
8630 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
8631 ] => {
8632 Ok => {
8633 b"KDxFYS_RE..." => {
8634 FunctionType {
8635 cv_qualifiers: CvQualifiers {
8636 restrict: false,
8637 volatile: false,
8638 const_: true,
8639 },
8640 transaction_safe: true,
8641 extern_c: true,
8642 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
8643 ref_qualifier: Some(RefQualifier::LValueRef),
8644 },
8645 b"...",
8646 []
8647 }
8648 b"DxFYS_RE..." => {
8649 FunctionType {
8650 cv_qualifiers: CvQualifiers {
8651 restrict: false,
8652 volatile: false,
8653 const_: false,
8654 },
8655 transaction_safe: true,
8656 extern_c: true,
8657 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
8658 ref_qualifier: Some(RefQualifier::LValueRef),
8659 },
8660 b"...",
8661 []
8662 }
8663 b"FYS_RE..." => {
8664 FunctionType {
8665 cv_qualifiers: CvQualifiers {
8666 restrict: false,
8667 volatile: false,
8668 const_: false,
8669 },
8670 transaction_safe: false,
8671 extern_c: true,
8672 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
8673 ref_qualifier: Some(RefQualifier::LValueRef),
8674 },
8675 b"...",
8676 []
8677 }
8678 b"FS_RE..." => {
8679 FunctionType {
8680 cv_qualifiers: CvQualifiers {
8681 restrict: false,
8682 volatile: false,
8683 const_: false,
8684 },
8685 transaction_safe: false,
8686 extern_c: false,
8687 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
8688 ref_qualifier: Some(RefQualifier::LValueRef),
8689 },
8690 b"...",
8691 []
8692 }
8693 b"FS_E..." => {
8694 FunctionType {
8695 cv_qualifiers: CvQualifiers {
8696 restrict: false,
8697 volatile: false,
8698 const_: false,
8699 },
8700 transaction_safe: false,
8701 extern_c: false,
8702 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
8703 ref_qualifier: None,
8704 },
8705 b"...",
8706 []
8707 }
8708 }
8709 Err => {
8710 b"DFYS_E" => Error::UnexpectedText,
8711 b"KKFS_E" => Error::UnexpectedText,
8712 b"FYS_..." => Error::UnexpectedText,
8713 b"FYS_" => Error::UnexpectedEnd,
8714 b"F" => Error::UnexpectedEnd,
8715 b"" => Error::UnexpectedEnd,
8716 }
8717 }
8718 });
8719 }
8720
8721 #[test]
parse_bare_function_type()8722 fn parse_bare_function_type() {
8723 assert_parse!(BareFunctionType {
8724 with subs [
8725 Substitutable::Type(
8726 Type::PointerTo(
8727 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
8728 ] => {
8729 Ok => {
8730 b"S_S_..." => {
8731 BareFunctionType(vec![
8732 TypeHandle::BackReference(0),
8733 TypeHandle::BackReference(0),
8734 ]),
8735 b"...",
8736 []
8737 }
8738 }
8739 Err => {
8740 b"" => Error::UnexpectedEnd,
8741 }
8742 }
8743 });
8744 }
8745
8746 #[test]
parse_decltype()8747 fn parse_decltype() {
8748 assert_parse!(Decltype {
8749 Ok => {
8750 b"DTtrE..." => {
8751 Decltype::Expression(Expression::Rethrow),
8752 b"..."
8753 }
8754 b"DttrE..." => {
8755 Decltype::IdExpression(Expression::Rethrow),
8756 b"..."
8757 }
8758 }
8759 Err => {
8760 b"Dtrtz" => Error::UnexpectedText,
8761 b"DTrtz" => Error::UnexpectedText,
8762 b"Dz" => Error::UnexpectedText,
8763 b"Dtrt" => Error::UnexpectedText,
8764 b"DTrt" => Error::UnexpectedText,
8765 b"Dt" => Error::UnexpectedEnd,
8766 b"DT" => Error::UnexpectedEnd,
8767 b"D" => Error::UnexpectedEnd,
8768 b"" => Error::UnexpectedEnd,
8769 }
8770 });
8771 }
8772
8773 #[test]
parse_class_enum_type()8774 fn parse_class_enum_type() {
8775 assert_parse!(ClassEnumType {
8776 Ok => {
8777 b"3abc..." => {
8778 ClassEnumType::Named(
8779 Name::Unscoped(
8780 UnscopedName::Unqualified(
8781 UnqualifiedName::Source(
8782 SourceName(Identifier {
8783 start: 1,
8784 end: 4,
8785 }))))),
8786 b"..."
8787 }
8788 b"Ts3abc..." => {
8789 ClassEnumType::ElaboratedStruct(
8790 Name::Unscoped(
8791 UnscopedName::Unqualified(
8792 UnqualifiedName::Source(
8793 SourceName(Identifier {
8794 start: 3,
8795 end: 6,
8796 }))))),
8797 b"..."
8798 }
8799 b"Tu3abc..." => {
8800 ClassEnumType::ElaboratedUnion(
8801 Name::Unscoped(
8802 UnscopedName::Unqualified(
8803 UnqualifiedName::Source(
8804 SourceName(Identifier {
8805 start: 3,
8806 end: 6,
8807 }))))),
8808 b"..."
8809 }
8810 b"Te3abc..." => {
8811 ClassEnumType::ElaboratedEnum(
8812 Name::Unscoped(
8813 UnscopedName::Unqualified(
8814 UnqualifiedName::Source(
8815 SourceName(Identifier {
8816 start: 3,
8817 end: 6,
8818 }))))),
8819 b"..."
8820 }
8821 }
8822 Err => {
8823 b"zzz" => Error::UnexpectedText,
8824 b"Tzzz" => Error::UnexpectedText,
8825 b"T" => Error::UnexpectedEnd,
8826 b"" => Error::UnexpectedEnd,
8827 }
8828 });
8829 }
8830
8831 #[test]
parse_array_type()8832 fn parse_array_type() {
8833 assert_parse!(ArrayType {
8834 with subs [
8835 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
8836 ] => {
8837 Ok => {
8838 b"A10_S_..." => {
8839 ArrayType::DimensionNumber(10, TypeHandle::BackReference(0)),
8840 b"...",
8841 []
8842 }
8843 b"A10_Sb..." => {
8844 ArrayType::DimensionNumber(10,
8845 TypeHandle::WellKnown(
8846 WellKnownComponent::StdString1)),
8847 b"...",
8848 []
8849 }
8850 b"Atr_S_..." => {
8851 ArrayType::DimensionExpression(Expression::Rethrow,
8852 TypeHandle::BackReference(0)),
8853 b"...",
8854 []
8855 }
8856 b"A_S_..." => {
8857 ArrayType::NoDimension(TypeHandle::BackReference(0)),
8858 b"...",
8859 []
8860 }
8861 }
8862 Err => {
8863 b"A10_" => Error::UnexpectedEnd,
8864 b"A10" => Error::UnexpectedEnd,
8865 b"A" => Error::UnexpectedEnd,
8866 b"" => Error::UnexpectedEnd,
8867 b"A10_..." => Error::UnexpectedText,
8868 b"A10..." => Error::UnexpectedText,
8869 b"A..." => Error::UnexpectedText,
8870 b"..." => Error::UnexpectedText,
8871 }
8872 }
8873 });
8874 }
8875
8876 #[test]
parse_vector_type()8877 fn parse_vector_type() {
8878 assert_parse!(VectorType {
8879 with subs [
8880 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
8881 ] => {
8882 Ok => {
8883 b"Dv10_S_..." => {
8884 VectorType::DimensionNumber(10, TypeHandle::BackReference(0)),
8885 b"...",
8886 []
8887 }
8888 b"Dv10_Sb..." => {
8889 VectorType::DimensionNumber(10,
8890 TypeHandle::WellKnown(
8891 WellKnownComponent::StdString1)),
8892 b"...",
8893 []
8894 }
8895 b"Dv_tr_S_..." => {
8896 VectorType::DimensionExpression(Expression::Rethrow,
8897 TypeHandle::BackReference(0)),
8898 b"...",
8899 []
8900 }
8901 }
8902 Err => {
8903 b"Dq" => Error::UnexpectedText,
8904 b"Dv" => Error::UnexpectedEnd,
8905 b"Dv42_" => Error::UnexpectedEnd,
8906 b"Dv42_..." => Error::UnexpectedText,
8907 b"Dvtr_" => Error::UnexpectedText,
8908 b"" => Error::UnexpectedEnd,
8909 b"..." => Error::UnexpectedText,
8910 }
8911 }
8912 });
8913 }
8914
8915 #[test]
parse_pointer_to_member_type()8916 fn parse_pointer_to_member_type() {
8917 assert_parse!(PointerToMemberType {
8918 with subs [
8919 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
8920 ] => {
8921 Ok => {
8922 b"MS_S_..." => {
8923 PointerToMemberType(TypeHandle::BackReference(0),
8924 TypeHandle::BackReference(0)),
8925 b"...",
8926 []
8927 }
8928 }
8929 Err => {
8930 b"MS_S" => Error::UnexpectedEnd,
8931 b"MS_" => Error::UnexpectedEnd,
8932 b"MS" => Error::UnexpectedEnd,
8933 b"M" => Error::UnexpectedEnd,
8934 b"" => Error::UnexpectedEnd,
8935 b"MS_..." => Error::UnexpectedText,
8936 b"M..." => Error::UnexpectedText,
8937 b"..." => Error::UnexpectedText,
8938 }
8939 }
8940 });
8941 }
8942
8943 #[test]
parse_template_template_param_handle()8944 fn parse_template_template_param_handle() {
8945 assert_parse!(TemplateTemplateParamHandle {
8946 with subs [
8947 Substitutable::TemplateTemplateParam(TemplateTemplateParam(TemplateParam(0)))
8948 ] => {
8949 Ok => {
8950 b"S_..." => {
8951 TemplateTemplateParamHandle::BackReference(0),
8952 b"...",
8953 []
8954 }
8955 b"T1_..." => {
8956 TemplateTemplateParamHandle::BackReference(1),
8957 b"...",
8958 [
8959 Substitutable::TemplateTemplateParam(TemplateTemplateParam(TemplateParam(2)))
8960 ]
8961 }
8962 }
8963 Err => {
8964 b"S" => Error::UnexpectedText,
8965 b"T" => Error::UnexpectedEnd,
8966 b"" => Error::UnexpectedEnd,
8967 b"S..." => Error::UnexpectedText,
8968 b"T..." => Error::UnexpectedText,
8969 b"..." => Error::UnexpectedText,
8970 }
8971 }
8972 });
8973 }
8974
8975 #[test]
parse_template_args()8976 fn parse_template_args() {
8977 assert_parse!(TemplateArgs {
8978 with subs [
8979 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
8980 ] => {
8981 Ok => {
8982 b"IS_E..." => {
8983 TemplateArgs(vec![TemplateArg::Type(TypeHandle::BackReference(0))]),
8984 b"...",
8985 []
8986 }
8987 b"IS_S_S_S_E..." => {
8988 TemplateArgs(vec![
8989 TemplateArg::Type(TypeHandle::BackReference(0)),
8990 TemplateArg::Type(TypeHandle::BackReference(0)),
8991 TemplateArg::Type(TypeHandle::BackReference(0)),
8992 TemplateArg::Type(TypeHandle::BackReference(0)),
8993 ]),
8994 b"...",
8995 []
8996 }
8997 }
8998 Err => {
8999 b"zzz" => Error::UnexpectedText,
9000 b"IE" => Error::UnexpectedText,
9001 b"IS_" => Error::UnexpectedEnd,
9002 b"I" => Error::UnexpectedEnd,
9003 b"" => Error::UnexpectedEnd,
9004 }
9005 }
9006 });
9007 }
9008
9009 #[test]
parse_template_arg()9010 fn parse_template_arg() {
9011 assert_parse!(TemplateArg {
9012 with subs [
9013 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9014 ] => {
9015 Ok => {
9016 b"S_..." => {
9017 TemplateArg::Type(TypeHandle::BackReference(0)),
9018 b"...",
9019 []
9020 }
9021 b"XtrE..." => {
9022 TemplateArg::Expression(Expression::Rethrow),
9023 b"...",
9024 []
9025 }
9026 b"XsrS_1QE..." => {
9027 TemplateArg::Expression(
9028 Expression::UnresolvedName(
9029 UnresolvedName::Nested1(
9030 UnresolvedTypeHandle::BackReference(0),
9031 vec![],
9032 BaseUnresolvedName::Name(
9033 SimpleId(
9034 SourceName(Identifier {
9035 start: 6,
9036 end: 7
9037 }),
9038 None
9039 )
9040 )
9041 )
9042 )
9043 ),
9044 b"...",
9045 []
9046 }
9047 b"XsrS_1QIlEE..." => {
9048 TemplateArg::Expression(
9049 Expression::UnresolvedName(
9050 UnresolvedName::Nested1(
9051 UnresolvedTypeHandle::BackReference(0),
9052 vec![],
9053 BaseUnresolvedName::Name(
9054 SimpleId(
9055 SourceName(Identifier {
9056 start: 6,
9057 end: 7
9058 }),
9059 Some(
9060 TemplateArgs(
9061 vec![
9062 TemplateArg::Type(
9063 TypeHandle::Builtin(
9064 BuiltinType::Standard(
9065 StandardBuiltinType::Long
9066 )
9067 )
9068 )
9069 ]
9070 )
9071 )
9072 )
9073 )
9074 )
9075 )
9076 ),
9077 b"...",
9078 []
9079 }
9080 b"LS_E..." => {
9081 TemplateArg::SimpleExpression(
9082 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 3)),
9083 b"...",
9084 []
9085 }
9086 b"JE..." => {
9087 TemplateArg::ArgPack(vec![]),
9088 b"...",
9089 []
9090 }
9091 b"JS_XtrELS_EJEE..." => {
9092 TemplateArg::ArgPack(vec![
9093 TemplateArg::Type(TypeHandle::BackReference(0)),
9094 TemplateArg::Expression(Expression::Rethrow),
9095 TemplateArg::SimpleExpression(
9096 ExprPrimary::Literal(TypeHandle::BackReference(0), 10, 10)),
9097 TemplateArg::ArgPack(vec![]),
9098 ]),
9099 b"...",
9100 []
9101 }
9102 }
9103 Err => {
9104 b"..." => Error::UnexpectedText,
9105 b"X..." => Error::UnexpectedText,
9106 b"J..." => Error::UnexpectedText,
9107 b"JS_..." => Error::UnexpectedText,
9108 b"JS_" => Error::UnexpectedEnd,
9109 b"X" => Error::UnexpectedEnd,
9110 b"J" => Error::UnexpectedEnd,
9111 b"" => Error::UnexpectedEnd,
9112 }
9113 }
9114 });
9115 }
9116
9117 #[test]
parse_expression()9118 fn parse_expression() {
9119 assert_parse!(Expression {
9120 with subs [
9121 Substitutable::Type(
9122 Type::PointerTo(TypeHandle::Builtin(
9123 BuiltinType::Standard(StandardBuiltinType::Int)))),
9124 ] => {
9125 Ok => {
9126 b"psLS_1E..." => {
9127 Expression::Unary(OperatorName::Simple(SimpleOperatorName::UnaryPlus),
9128 Box::new(Expression::Primary(
9129 ExprPrimary::Literal(
9130 TypeHandle::BackReference(0),
9131 5,
9132 6)))),
9133 b"...",
9134 []
9135 }
9136 b"rsLS_1ELS_1E..." => {
9137 Expression::Binary(OperatorName::Simple(SimpleOperatorName::Shr),
9138 Box::new(Expression::Primary(
9139 ExprPrimary::Literal(
9140 TypeHandle::BackReference(0),
9141 5,
9142 6))),
9143 Box::new(Expression::Primary(
9144 ExprPrimary::Literal(
9145 TypeHandle::BackReference(0),
9146 10,
9147 11)))),
9148 b"...",
9149 []
9150 }
9151 b"quLS_1ELS_2ELS_3E..." => {
9152 Expression::Ternary(OperatorName::Simple(SimpleOperatorName::Question),
9153 Box::new(Expression::Primary(
9154 ExprPrimary::Literal(
9155 TypeHandle::BackReference(0),
9156 5,
9157 6))),
9158 Box::new(Expression::Primary(
9159 ExprPrimary::Literal(
9160 TypeHandle::BackReference(0),
9161 10,
9162 11))),
9163 Box::new(Expression::Primary(
9164 ExprPrimary::Literal(
9165 TypeHandle::BackReference(0),
9166 15,
9167 16)))),
9168 b"...",
9169 []
9170 }
9171 b"pp_LS_1E..." => {
9172 Expression::PrefixInc(
9173 Box::new(Expression::Primary(
9174 ExprPrimary::Literal(
9175 TypeHandle::BackReference(0),
9176 6,
9177 7)))),
9178 b"...",
9179 []
9180 }
9181 b"mm_LS_1E..." => {
9182 Expression::PrefixDec(
9183 Box::new(Expression::Primary(
9184 ExprPrimary::Literal(
9185 TypeHandle::BackReference(0),
9186 6,
9187 7)))),
9188 b"...",
9189 []
9190 }
9191 b"clLS_1EE..." => {
9192 Expression::Call(
9193 Box::new(Expression::Primary(
9194 ExprPrimary::Literal(
9195 TypeHandle::BackReference(0),
9196 5,
9197 6))),
9198 vec![]),
9199 b"...",
9200 []
9201 }
9202 // ::= cv <type> <expression> # type (expression), conversion with one argument
9203 b"cvS_LS_1E..." => {
9204 Expression::ConversionOne(
9205 TypeHandle::BackReference(0),
9206 Box::new(Expression::Primary(
9207 ExprPrimary::Literal(
9208 TypeHandle::BackReference(0),
9209 7,
9210 8)))),
9211 b"...",
9212 []
9213 }
9214 b"cvS__LS_1ELS_1EE..." => {
9215 Expression::ConversionMany(
9216 TypeHandle::BackReference(0),
9217 vec![
9218 Expression::Primary(
9219 ExprPrimary::Literal(
9220 TypeHandle::BackReference(0),
9221 8,
9222 9)),
9223 Expression::Primary(
9224 ExprPrimary::Literal(
9225 TypeHandle::BackReference(0),
9226 13,
9227 14)),
9228 ]),
9229 b"...",
9230 []
9231 }
9232 b"tlS_LS_1ELS_1EE..." => {
9233 Expression::ConversionBraced(
9234 TypeHandle::BackReference(0),
9235 vec![
9236 Expression::Primary(
9237 ExprPrimary::Literal(
9238 TypeHandle::BackReference(0),
9239 7,
9240 8)),
9241 Expression::Primary(
9242 ExprPrimary::Literal(
9243 TypeHandle::BackReference(0),
9244 12,
9245 13)),
9246 ]),
9247 b"...",
9248 []
9249 }
9250 b"ilLS_1EE..." => {
9251 Expression::BracedInitList(
9252 Box::new(Expression::Primary(
9253 ExprPrimary::Literal(
9254 TypeHandle::BackReference(0),
9255 5,
9256 6)))),
9257 b"...",
9258 []
9259 }
9260 b"gsnwLS_1E_S_E..." => {
9261 Expression::GlobalNew(
9262 vec![
9263 Expression::Primary(
9264 ExprPrimary::Literal(
9265 TypeHandle::BackReference(0),
9266 7,
9267 8))
9268 ],
9269 TypeHandle::BackReference(0),
9270 None),
9271 b"...",
9272 []
9273 }
9274 b"nwLS_1E_S_E..." => {
9275 Expression::New(
9276 vec![
9277 Expression::Primary(
9278 ExprPrimary::Literal(
9279 TypeHandle::BackReference(0),
9280 5,
9281 6))
9282 ],
9283 TypeHandle::BackReference(0),
9284 None),
9285 b"...",
9286 []
9287 }
9288 b"gsnwLS_1E_S_piE..." => {
9289 Expression::GlobalNew(
9290 vec![
9291 Expression::Primary(
9292 ExprPrimary::Literal(
9293 TypeHandle::BackReference(0),
9294 7,
9295 8))
9296 ],
9297 TypeHandle::BackReference(0),
9298 Some(Initializer(vec![]))),
9299 b"...",
9300 []
9301 }
9302 b"nwLS_1E_S_piE..." => {
9303 Expression::New(
9304 vec![
9305 Expression::Primary(
9306 ExprPrimary::Literal(
9307 TypeHandle::BackReference(0),
9308 5,
9309 6))
9310 ],
9311 TypeHandle::BackReference(0),
9312 Some(Initializer(vec![]))),
9313 b"...",
9314 []
9315 }
9316 b"gsnaLS_1E_S_E..." => {
9317 Expression::GlobalNewArray(
9318 vec![
9319 Expression::Primary(
9320 ExprPrimary::Literal(
9321 TypeHandle::BackReference(0),
9322 7,
9323 8))
9324 ],
9325 TypeHandle::BackReference(0),
9326 None),
9327 b"...",
9328 []
9329 }
9330 b"naLS_1E_S_E..." => {
9331 Expression::NewArray(
9332 vec![
9333 Expression::Primary(
9334 ExprPrimary::Literal(
9335 TypeHandle::BackReference(0),
9336 5,
9337 6))
9338 ],
9339 TypeHandle::BackReference(0),
9340 None),
9341 b"...",
9342 []
9343 }
9344 b"gsnaLS_1E_S_piE..." => {
9345 Expression::GlobalNewArray(
9346 vec![
9347 Expression::Primary(
9348 ExprPrimary::Literal(
9349 TypeHandle::BackReference(0),
9350 7,
9351 8))
9352 ],
9353 TypeHandle::BackReference(0),
9354 Some(Initializer(vec![]))),
9355 b"...",
9356 []
9357 }
9358 b"naLS_1E_S_piE..." => {
9359 Expression::NewArray(
9360 vec![
9361 Expression::Primary(
9362 ExprPrimary::Literal(
9363 TypeHandle::BackReference(0),
9364 5,
9365 6))
9366 ],
9367 TypeHandle::BackReference(0),
9368 Some(Initializer(vec![]))),
9369 b"...",
9370 []
9371 }
9372 b"gsdlLS_1E..." => {
9373 Expression::GlobalDelete(
9374 Box::new(Expression::Primary(
9375 ExprPrimary::Literal(
9376 TypeHandle::BackReference(0),
9377 7,
9378 8)))),
9379 b"...",
9380 []
9381 }
9382 b"dlLS_1E..." => {
9383 Expression::Delete(
9384 Box::new(Expression::Primary(
9385 ExprPrimary::Literal(
9386 TypeHandle::BackReference(0),
9387 5,
9388 6)))),
9389 b"...",
9390 []
9391 }
9392 // ::= [gs] da <expression> # delete[] expression
9393 b"gsdaLS_1E..." => {
9394 Expression::GlobalDeleteArray(
9395 Box::new(Expression::Primary(
9396 ExprPrimary::Literal(
9397 TypeHandle::BackReference(0),
9398 7,
9399 8)))),
9400 b"...",
9401 []
9402 }
9403 b"daLS_1E..." => {
9404 Expression::DeleteArray(
9405 Box::new(Expression::Primary(
9406 ExprPrimary::Literal(
9407 TypeHandle::BackReference(0),
9408 5,
9409 6)))),
9410 b"...",
9411 []
9412 }
9413 b"dcS_LS_1E..." => {
9414 Expression::DynamicCast(
9415 TypeHandle::BackReference(0),
9416 Box::new(Expression::Primary(
9417 ExprPrimary::Literal(
9418 TypeHandle::BackReference(0),
9419 7,
9420 8)))),
9421 b"...",
9422 []
9423 }
9424 b"scS_LS_1E..." => {
9425 Expression::StaticCast(
9426 TypeHandle::BackReference(0),
9427 Box::new(Expression::Primary(
9428 ExprPrimary::Literal(
9429 TypeHandle::BackReference(0),
9430 7,
9431 8)))),
9432 b"...",
9433 []
9434 }
9435 b"ccS_LS_1E..." => {
9436 Expression::ConstCast(
9437 TypeHandle::BackReference(0),
9438 Box::new(Expression::Primary(
9439 ExprPrimary::Literal(
9440 TypeHandle::BackReference(0),
9441 7,
9442 8)))),
9443 b"...",
9444 []
9445 }
9446 b"rcS_LS_1E..." => {
9447 Expression::ReinterpretCast(
9448 TypeHandle::BackReference(0),
9449 Box::new(Expression::Primary(
9450 ExprPrimary::Literal(
9451 TypeHandle::BackReference(0),
9452 7,
9453 8)))),
9454 b"...",
9455 []
9456 }
9457 b"tiS_..." => {
9458 Expression::TypeidType(TypeHandle::BackReference(0)),
9459 b"...",
9460 []
9461 }
9462 b"teLS_1E..." => {
9463 Expression::TypeidExpr(
9464 Box::new(Expression::Primary(
9465 ExprPrimary::Literal(
9466 TypeHandle::BackReference(0),
9467 5,
9468 6)))),
9469 b"...",
9470 []
9471 }
9472 b"stS_..." => {
9473 Expression::SizeofType(TypeHandle::BackReference(0)),
9474 b"...",
9475 []
9476 }
9477 b"szLS_1E..." => {
9478 Expression::SizeofExpr(
9479 Box::new(Expression::Primary(
9480 ExprPrimary::Literal(
9481 TypeHandle::BackReference(0),
9482 5,
9483 6)))),
9484 b"...",
9485 []
9486 }
9487 b"atS_..." => {
9488 Expression::AlignofType(TypeHandle::BackReference(0)),
9489 b"...",
9490 []
9491 }
9492 b"azLS_1E..." => {
9493 Expression::AlignofExpr(
9494 Box::new(Expression::Primary(
9495 ExprPrimary::Literal(
9496 TypeHandle::BackReference(0),
9497 5,
9498 6)))),
9499 b"...",
9500 []
9501 }
9502 b"nxLS_1E..." => {
9503 Expression::Noexcept(
9504 Box::new(Expression::Primary(
9505 ExprPrimary::Literal(
9506 TypeHandle::BackReference(0),
9507 5,
9508 6)))),
9509 b"...",
9510 []
9511 }
9512 b"T_..." => {
9513 Expression::TemplateParam(TemplateParam(0)),
9514 b"...",
9515 []
9516 }
9517 b"fp_..." => {
9518 Expression::FunctionParam(FunctionParam(0, CvQualifiers::default(), Some(0))),
9519 b"...",
9520 []
9521 }
9522 b"dtT_3abc..." => {
9523 Expression::Member(
9524 Box::new(Expression::TemplateParam(TemplateParam(0))),
9525 MemberName(
9526 Name::Unscoped(
9527 UnscopedName::Unqualified(
9528 UnqualifiedName::Source(
9529 SourceName(
9530 Identifier {
9531 start: 5,
9532 end: 8,
9533 })))))),
9534 b"...",
9535 []
9536 }
9537 b"ptT_3abc..." => {
9538 Expression::DerefMember(
9539 Box::new(Expression::TemplateParam(TemplateParam(0))),
9540 MemberName(
9541 Name::Unscoped(
9542 UnscopedName::Unqualified(
9543 UnqualifiedName::Source(
9544 SourceName(
9545 Identifier {
9546 start: 5,
9547 end: 8,
9548 })))))),
9549 b"...",
9550 []
9551 }
9552 b"dtfp_clI3abcE..." => {
9553 Expression::Member(
9554 Box::new(Expression::FunctionParam(FunctionParam(0, CvQualifiers::default(), Some(0)))),
9555 MemberName(
9556 Name::UnscopedTemplate(
9557 UnscopedTemplateNameHandle::NonSubstitution(NonSubstitution(0)),
9558 TemplateArgs(vec![
9559 TemplateArg::Type(
9560 TypeHandle::BackReference(1))])))),
9561 b"...",
9562 [
9563 Substitutable::Type(
9564 Type::ClassEnum(
9565 ClassEnumType::Named(
9566 Name::Unscoped(
9567 UnscopedName::Unqualified(
9568 UnqualifiedName::Source(
9569 SourceName(
9570 Identifier {
9571 start: 9,
9572 end: 12
9573 })))))))
9574 ]
9575 }
9576 // ::= ds <expression> <expression> # expr.*expr
9577 b"dsT_T_..." => {
9578 Expression::PointerToMember(
9579 Box::new(Expression::TemplateParam(TemplateParam(0))),
9580 Box::new(Expression::TemplateParam(TemplateParam(0)))),
9581 b"...",
9582 []
9583 }
9584 b"sZT_..." => {
9585 Expression::SizeofTemplatePack(TemplateParam(0)),
9586 b"...",
9587 []
9588 }
9589 b"sZfp_..." => {
9590 Expression::SizeofFunctionPack(
9591 FunctionParam(0, CvQualifiers::default(), Some(0))),
9592 b"...",
9593 []
9594 }
9595 b"sPE..." => {
9596 Expression::SizeofCapturedTemplatePack(vec![]),
9597 b"...",
9598 []
9599 }
9600 b"spT_..." => {
9601 Expression::PackExpansion(
9602 Box::new(Expression::TemplateParam(TemplateParam(0)))),
9603 b"...",
9604 []
9605 }
9606 b"twT_..." => {
9607 Expression::Throw(Box::new(Expression::TemplateParam(TemplateParam(0)))),
9608 b"...",
9609 []
9610 }
9611 b"tr..." => {
9612 Expression::Rethrow,
9613 b"...",
9614 []
9615 }
9616 b"3abc..." => {
9617 Expression::UnresolvedName(
9618 UnresolvedName::Name(
9619 BaseUnresolvedName::Name(
9620 SimpleId(
9621 SourceName(Identifier {
9622 start: 1,
9623 end: 4,
9624 }),
9625 None)))),
9626 b"...",
9627 []
9628 }
9629 b"L_Z3abcE..." => {
9630 Expression::Primary(
9631 ExprPrimary::External(
9632 MangledName::Encoding(
9633 Encoding::Data(
9634 Name::Unscoped(
9635 UnscopedName::Unqualified(
9636 UnqualifiedName::Source(
9637 SourceName(Identifier {
9638 start: 4,
9639 end: 7,
9640 }))))), vec![]))),
9641 b"...",
9642 []
9643 }
9644 // An expression where arity matters
9645 b"cldtdefpT4TypeadsrT_5EnterE..." => {
9646 Expression::Call(
9647 Box::new(Expression::Member(
9648 Box::new(Expression::Unary(OperatorName::Simple(SimpleOperatorName::Deref),
9649 Box::new(Expression::FunctionParam(
9650 FunctionParam(0,
9651 CvQualifiers::default(),
9652 None)
9653 ))
9654 )),
9655 MemberName(
9656 Name::Unscoped(
9657 UnscopedName::Unqualified(
9658 UnqualifiedName::Source(
9659 SourceName(Identifier {
9660 start: 10,
9661 end: 14,
9662 })))
9663 )
9664 )
9665 )),
9666 vec![Expression::Unary(OperatorName::Simple(SimpleOperatorName::AddressOf),
9667 Box::new(Expression::UnresolvedName(
9668 UnresolvedName::Nested1(
9669 UnresolvedTypeHandle::BackReference(1),
9670 vec![],
9671 BaseUnresolvedName::Name(
9672 SimpleId(
9673 SourceName(Identifier {
9674 start: 21,
9675 end: 26
9676 }
9677 ),
9678 None
9679 )
9680 )
9681 ))))]
9682 ),
9683 b"...",
9684 [
9685 Substitutable::UnresolvedType(UnresolvedType::Template(TemplateParam(0), None))
9686 ]
9687 }
9688 }
9689 Err => {
9690 b"dtStfp_clI3abcE..." => Error::UnexpectedText,
9691 }
9692 }
9693 });
9694 }
9695
9696 #[test]
parse_unresolved_name()9697 fn parse_unresolved_name() {
9698 assert_parse!(UnresolvedName {
9699 with subs [
9700 Substitutable::UnresolvedType(
9701 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
9702 ] => {
9703 Ok => {
9704 b"gs3abc..." => {
9705 UnresolvedName::Global(BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
9706 start: 3,
9707 end: 6,
9708 }), None))),
9709 b"...",
9710 []
9711 }
9712 b"3abc..." => {
9713 UnresolvedName::Name(BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
9714 start: 1,
9715 end: 4,
9716 }), None))),
9717 b"...",
9718 []
9719 }
9720 b"srS_3abc..." => {
9721 UnresolvedName::Nested1(UnresolvedTypeHandle::BackReference(0),
9722 vec![],
9723 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
9724 start: 5,
9725 end: 8,
9726 }), None))),
9727 b"...",
9728 []
9729 }
9730 b"srNS_3abc3abcE3abc..." => {
9731 UnresolvedName::Nested1(
9732 UnresolvedTypeHandle::BackReference(0),
9733 vec![
9734 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
9735 start: 6,
9736 end: 9,
9737 }), None)),
9738 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
9739 start: 10,
9740 end: 13,
9741 }), None)),
9742 ],
9743 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
9744 start: 15,
9745 end: 18,
9746 }), None))),
9747 b"...",
9748 []
9749 }
9750 b"gssr3abcE3abc..." => {
9751 UnresolvedName::GlobalNested2(
9752 vec![
9753 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
9754 start: 5,
9755 end: 8,
9756 }), None)),
9757 ],
9758 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
9759 start: 10,
9760 end: 13,
9761 }), None))),
9762 b"...",
9763 []
9764 }
9765 b"sr3abcE3abc..." => {
9766 UnresolvedName::Nested2(
9767 vec![
9768 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
9769 start: 3,
9770 end: 6,
9771 }), None)),
9772 ],
9773 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
9774 start: 8,
9775 end: 11,
9776 }), None))),
9777 b"...",
9778 []
9779 }
9780 }
9781 Err => {
9782 b"zzzzzz" => Error::UnexpectedText,
9783 b"gszzz" => Error::UnexpectedText,
9784 b"gssrzzz" => Error::UnexpectedText,
9785 b"srNzzz" => Error::UnexpectedText,
9786 b"srzzz" => Error::UnexpectedText,
9787 b"srN3abczzzz" => Error::UnexpectedText,
9788 b"srN3abcE" => Error::UnexpectedText,
9789 b"srN3abc" => Error::UnexpectedText,
9790 b"srN" => Error::UnexpectedEnd,
9791 b"sr" => Error::UnexpectedEnd,
9792 b"gssr" => Error::UnexpectedEnd,
9793 b"gs" => Error::UnexpectedEnd,
9794 b"" => Error::UnexpectedEnd,
9795 }
9796 }
9797 });
9798 }
9799
9800 #[test]
parse_unresolved_type_handle()9801 fn parse_unresolved_type_handle() {
9802 assert_parse!(UnresolvedTypeHandle {
9803 with subs [
9804 Substitutable::UnresolvedType(
9805 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
9806 ] => {
9807 Ok => {
9808 b"S_..." => {
9809 UnresolvedTypeHandle::BackReference(0),
9810 b"...",
9811 []
9812 }
9813 b"T_..." => {
9814 UnresolvedTypeHandle::BackReference(1),
9815 b"...",
9816 [
9817 Substitutable::UnresolvedType(
9818 UnresolvedType::Template(TemplateParam(0), None)),
9819 ]
9820 }
9821 b"T_IS_E..." => {
9822 UnresolvedTypeHandle::BackReference(1),
9823 b"...",
9824 [
9825 Substitutable::UnresolvedType(
9826 UnresolvedType::Template(TemplateParam(0), Some(TemplateArgs(vec![
9827 TemplateArg::Type(TypeHandle::BackReference(0))
9828 ])))),
9829 ]
9830 }
9831 b"DTtrE..." => {
9832 UnresolvedTypeHandle::BackReference(1),
9833 b"...",
9834 [
9835 Substitutable::UnresolvedType(
9836 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow)))
9837 ]
9838
9839 }
9840 }
9841 Err => {
9842 b"zzzzzzz" => Error::UnexpectedText,
9843 b"" => Error::UnexpectedEnd,
9844 }
9845 }
9846 });
9847 }
9848
9849 #[test]
parse_unresolved_qualifier_level()9850 fn parse_unresolved_qualifier_level() {
9851 assert_parse!(UnresolvedQualifierLevel {
9852 with subs [
9853 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9854 ] => {
9855 Ok => {
9856 b"3abc..." => {
9857 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
9858 start: 1,
9859 end: 4,
9860 }), None)),
9861 b"...",
9862 []
9863 }
9864 b"3abcIS_E..." => {
9865 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
9866 start: 1,
9867 end: 4,
9868 }), Some(TemplateArgs(vec![
9869 TemplateArg::Type(TypeHandle::BackReference(0))
9870 ])))),
9871 b"...",
9872 []
9873 }
9874 }
9875 Err => {
9876 b"zzz" => Error::UnexpectedText,
9877 b"" => Error::UnexpectedEnd,
9878 }
9879 }
9880 });
9881 }
9882
9883 #[test]
parse_simple_id()9884 fn parse_simple_id() {
9885 assert_parse!(SimpleId {
9886 with subs [
9887 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9888 ] => {
9889 Ok => {
9890 b"3abc..." => {
9891 SimpleId(SourceName(Identifier {
9892 start: 1,
9893 end: 4,
9894 }), None),
9895 b"...",
9896 []
9897 }
9898 b"3abcIS_E..." => {
9899 SimpleId(SourceName(Identifier {
9900 start: 1,
9901 end: 4,
9902 }), Some(TemplateArgs(vec![
9903 TemplateArg::Type(TypeHandle::BackReference(0))
9904 ]))),
9905 b"...",
9906 []
9907 }
9908 }
9909 Err => {
9910 b"zzz" => Error::UnexpectedText,
9911 b"" => Error::UnexpectedEnd,
9912 }
9913 }
9914 });
9915 }
9916
9917 #[test]
parse_base_unresolved_name()9918 fn parse_base_unresolved_name() {
9919 assert_parse!(BaseUnresolvedName {
9920 with subs [
9921 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9922 ] => {
9923 Ok => {
9924 b"3abc..." => {
9925 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
9926 start: 1,
9927 end: 4,
9928 }), None)),
9929 b"...",
9930 []
9931 }
9932 b"onnw..." => {
9933 BaseUnresolvedName::Operator(OperatorName::Simple(SimpleOperatorName::New), None),
9934 b"...",
9935 []
9936 }
9937 b"onnwIS_E..." => {
9938 BaseUnresolvedName::Operator(OperatorName::Simple(SimpleOperatorName::New),
9939 Some(TemplateArgs(vec![
9940 TemplateArg::Type(TypeHandle::BackReference(0))
9941 ]))),
9942 b"...",
9943 []
9944 }
9945 b"dn3abc..." => {
9946 BaseUnresolvedName::Destructor(DestructorName::Name(SimpleId(SourceName(Identifier {
9947 start: 3,
9948 end: 6,
9949 }), None))),
9950 b"...",
9951 []
9952 }
9953 }
9954 Err => {
9955 b"ozzz" => Error::UnexpectedText,
9956 b"dzzz" => Error::UnexpectedText,
9957 b"dn" => Error::UnexpectedEnd,
9958 b"on" => Error::UnexpectedEnd,
9959 b"" => Error::UnexpectedEnd,
9960 }
9961 }
9962 });
9963 }
9964
9965 #[test]
parse_destructor_name()9966 fn parse_destructor_name() {
9967 assert_parse!(DestructorName {
9968 with subs [
9969 Substitutable::UnresolvedType(
9970 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
9971 ] => {
9972 Ok => {
9973 b"S_..." => {
9974 DestructorName::Unresolved(UnresolvedTypeHandle::BackReference(0)),
9975 b"...",
9976 []
9977 }
9978 b"3abc..." => {
9979 DestructorName::Name(SimpleId(SourceName(Identifier {
9980 start: 1,
9981 end: 4,
9982 }), None)),
9983 b"...",
9984 []
9985 }
9986 }
9987 Err => {
9988 b"zzz" => Error::UnexpectedText,
9989 b"" => Error::UnexpectedEnd,
9990 }
9991 }
9992 });
9993 }
9994
9995 #[test]
parse_expr_primary()9996 fn parse_expr_primary() {
9997 assert_parse!(ExprPrimary {
9998 with subs [
9999 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10000 ] => {
10001 Ok => {
10002 b"LS_12345E..." => {
10003 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 8),
10004 b"...",
10005 []
10006 }
10007 b"LS_E..." => {
10008 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 3),
10009 b"...",
10010 []
10011 }
10012 b"L_Z3abcE..." => {
10013 ExprPrimary::External(
10014 MangledName::Encoding(
10015 Encoding::Data(
10016 Name::Unscoped(
10017 UnscopedName::Unqualified(
10018 UnqualifiedName::Source(
10019 SourceName(Identifier {
10020 start: 4,
10021 end: 7,
10022 }))))), vec![])),
10023 b"...",
10024 []
10025 }
10026 }
10027 Err => {
10028 b"zzz" => Error::UnexpectedText,
10029 b"LS_zzz" => Error::UnexpectedEnd,
10030 b"LS_12345" => Error::UnexpectedEnd,
10031 b"LS_" => Error::UnexpectedEnd,
10032 b"L" => Error::UnexpectedEnd,
10033 b"" => Error::UnexpectedEnd,
10034 }
10035 }
10036 });
10037 }
10038
10039 #[test]
parse_initializer()10040 fn parse_initializer() {
10041 assert_parse!(Initializer {
10042 Ok => {
10043 b"piE..." => {
10044 Initializer(vec![]),
10045 b"..."
10046 }
10047 b"pitrtrtrE..." => {
10048 Initializer(vec![
10049 Expression::Rethrow,
10050 Expression::Rethrow,
10051 Expression::Rethrow,
10052 ]),
10053 b"..."
10054 }
10055 }
10056 Err => {
10057 b"pirtrtrt..." => Error::UnexpectedText,
10058 b"pi..." => Error::UnexpectedText,
10059 b"..." => Error::UnexpectedText,
10060 b"pirt" => Error::UnexpectedText,
10061 b"pi" => Error::UnexpectedEnd,
10062 b"p" => Error::UnexpectedEnd,
10063 b"" => Error::UnexpectedEnd,
10064 }
10065 });
10066 }
10067
10068 #[test]
parse_local_name()10069 fn parse_local_name() {
10070 assert_parse!(LocalName {
10071 Ok => {
10072 b"Z3abcE3def_0..." => {
10073 LocalName::Relative(
10074 Box::new(Encoding::Data(
10075 Name::Unscoped(
10076 UnscopedName::Unqualified(
10077 UnqualifiedName::Source(
10078 SourceName(Identifier {
10079 start: 2,
10080 end: 5,
10081 })))))),
10082 Some(Box::new(Name::Unscoped(
10083 UnscopedName::Unqualified(
10084 UnqualifiedName::Source(
10085 SourceName(Identifier {
10086 start: 7,
10087 end: 10,
10088 })))))),
10089 Some(Discriminator(0))),
10090 b"..."
10091 }
10092 b"Z3abcE3def..." => {
10093 LocalName::Relative(
10094 Box::new(Encoding::Data(
10095 Name::Unscoped(
10096 UnscopedName::Unqualified(
10097 UnqualifiedName::Source(
10098 SourceName(Identifier {
10099 start: 2,
10100 end: 5,
10101 })))))),
10102 Some(Box::new(Name::Unscoped(
10103 UnscopedName::Unqualified(
10104 UnqualifiedName::Source(
10105 SourceName(Identifier {
10106 start: 7,
10107 end: 10,
10108 })))))),
10109 None),
10110 b"..."
10111 }
10112 b"Z3abcEs_0..." => {
10113 LocalName::Relative(
10114 Box::new(Encoding::Data(
10115 Name::Unscoped(
10116 UnscopedName::Unqualified(
10117 UnqualifiedName::Source(
10118 SourceName(Identifier {
10119 start: 2,
10120 end: 5,
10121 })))))),
10122 None,
10123 Some(Discriminator(0))),
10124 b"..."
10125 }
10126 b"Z3abcEs..." => {
10127 LocalName::Relative(
10128 Box::new(Encoding::Data(
10129 Name::Unscoped(
10130 UnscopedName::Unqualified(
10131 UnqualifiedName::Source(
10132 SourceName(Identifier {
10133 start: 2,
10134 end: 5,
10135 })))))),
10136 None,
10137 None),
10138 b"..."
10139 }
10140 b"Z3abcEd1_3abc..." => {
10141 LocalName::Default(
10142 Box::new(Encoding::Data(
10143 Name::Unscoped(
10144 UnscopedName::Unqualified(
10145 UnqualifiedName::Source(
10146 SourceName(Identifier {
10147 start: 2,
10148 end: 5,
10149 })))))),
10150 Some(1),
10151 Box::new(Name::Unscoped(
10152 UnscopedName::Unqualified(
10153 UnqualifiedName::Source(
10154 SourceName(Identifier {
10155 start: 10,
10156 end: 13,
10157 })))))),
10158 b"..."
10159 }
10160 b"Z3abcEd_3abc..." => {
10161 LocalName::Default(
10162 Box::new(Encoding::Data(
10163 Name::Unscoped(
10164 UnscopedName::Unqualified(
10165 UnqualifiedName::Source(
10166 SourceName(Identifier {
10167 start: 2,
10168 end: 5,
10169 })))))),
10170 None,
10171 Box::new(Name::Unscoped(
10172 UnscopedName::Unqualified(
10173 UnqualifiedName::Source(
10174 SourceName(Identifier {
10175 start: 9,
10176 end: 12,
10177 })))))),
10178 b"..."
10179 }
10180 }
10181 Err => {
10182 b"A" => Error::UnexpectedText,
10183 b"Z1a" => Error::UnexpectedEnd,
10184 b"Z1aE" => Error::UnexpectedEnd,
10185 b"Z" => Error::UnexpectedEnd,
10186 b"" => Error::UnexpectedEnd,
10187 }
10188 });
10189 }
10190
10191 #[test]
parse_closure_type_name()10192 fn parse_closure_type_name() {
10193 assert_parse!(ClosureTypeName {
10194 Ok => {
10195 b"UlvE_..." => {
10196 ClosureTypeName(LambdaSig(vec![]), None),
10197 b"..."
10198 }
10199 b"UlvE36_..." => {
10200 ClosureTypeName(LambdaSig(vec![]), Some(36)),
10201 b"..."
10202 }
10203 }
10204 Err => {
10205 b"UlvE36zzz" => Error::UnexpectedText,
10206 b"UlvEzzz" => Error::UnexpectedText,
10207 b"Ulvzzz" => Error::UnexpectedText,
10208 b"zzz" => Error::UnexpectedText,
10209 b"UlvE10" => Error::UnexpectedEnd,
10210 b"UlvE" => Error::UnexpectedEnd,
10211 b"Ulv" => Error::UnexpectedEnd,
10212 b"Ul" => Error::UnexpectedEnd,
10213 b"U" => Error::UnexpectedEnd,
10214 b"" => Error::UnexpectedEnd,
10215 }
10216 });
10217 }
10218
10219 #[test]
parse_lambda_sig()10220 fn parse_lambda_sig() {
10221 assert_parse!(LambdaSig {
10222 with subs [
10223 Substitutable::Type(
10224 Type::PointerTo(
10225 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Bool))))
10226 ] => {
10227 Ok => {
10228 b"v..." => {
10229 LambdaSig(vec![]),
10230 b"...",
10231 []
10232 }
10233 b"S_S_S_..." => {
10234 LambdaSig(vec![
10235 TypeHandle::BackReference(0),
10236 TypeHandle::BackReference(0),
10237 TypeHandle::BackReference(0),
10238 ]),
10239 b"...",
10240 []
10241 }
10242 }
10243 Err => {
10244 b"..." => Error::UnexpectedText,
10245 b"S" => Error::UnexpectedEnd,
10246 b"" => Error::UnexpectedEnd,
10247 }
10248 }
10249 });
10250 }
10251
10252 #[test]
parse_substitution()10253 fn parse_substitution() {
10254 assert_parse!(Substitution {
10255 with subs [
10256 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow))),
10257 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow))),
10258 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10259 ] => {
10260 Ok => {
10261 b"S_..." => {
10262 Substitution::BackReference(0),
10263 b"...",
10264 []
10265 }
10266 b"S1_..." => {
10267 Substitution::BackReference(2),
10268 b"...",
10269 []
10270 }
10271 b"St..." => {
10272 Substitution::WellKnown(WellKnownComponent::Std),
10273 b"...",
10274 []
10275 }
10276 b"Sa..." => {
10277 Substitution::WellKnown(WellKnownComponent::StdAllocator),
10278 b"...",
10279 []
10280 }
10281 b"Sb..." => {
10282 Substitution::WellKnown(WellKnownComponent::StdString1),
10283 b"...",
10284 []
10285 }
10286 b"Ss..." => {
10287 Substitution::WellKnown(WellKnownComponent::StdString2),
10288 b"...",
10289 []
10290 }
10291 b"Si..." => {
10292 Substitution::WellKnown(WellKnownComponent::StdIstream),
10293 b"...",
10294 []
10295 }
10296 b"So..." => {
10297 Substitution::WellKnown(WellKnownComponent::StdOstream),
10298 b"...",
10299 []
10300 }
10301 b"Sd..." => {
10302 Substitution::WellKnown(WellKnownComponent::StdIostream),
10303 b"...",
10304 []
10305 }
10306 }
10307 Err => {
10308 b"S999_" => Error::BadBackReference,
10309 b"Sz" => Error::UnexpectedText,
10310 b"zzz" => Error::UnexpectedText,
10311 b"S1" => Error::UnexpectedEnd,
10312 b"S" => Error::UnexpectedEnd,
10313 b"" => Error::UnexpectedEnd,
10314 }
10315 }
10316 });
10317 }
10318
10319 #[test]
parse_special_name()10320 fn parse_special_name() {
10321 assert_parse!(SpecialName {
10322 Ok => {
10323 b"TVi..." => {
10324 SpecialName::VirtualTable(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10325 b"..."
10326 }
10327 b"TTi..." => {
10328 SpecialName::Vtt(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10329 b"..."
10330 }
10331 b"TIi..." => {
10332 SpecialName::Typeinfo(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10333 b"..."
10334 }
10335 b"TSi..." => {
10336 SpecialName::TypeinfoName(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10337 b"..."
10338 }
10339 b"Tv42_36_3abc..." => {
10340 SpecialName::VirtualOverrideThunk(
10341 CallOffset::Virtual(VOffset(42, 36)),
10342 Box::new(Encoding::Data(
10343 Name::Unscoped(
10344 UnscopedName::Unqualified(
10345 UnqualifiedName::Source(
10346 SourceName(Identifier {
10347 start: 9,
10348 end: 12,
10349 }))))))),
10350 b"..."
10351 }
10352 b"Tcv42_36_v42_36_3abc..." => {
10353 SpecialName::VirtualOverrideThunkCovariant(
10354 CallOffset::Virtual(VOffset(42, 36)),
10355 CallOffset::Virtual(VOffset(42, 36)),
10356 Box::new(Encoding::Data(
10357 Name::Unscoped(
10358 UnscopedName::Unqualified(
10359 UnqualifiedName::Source(
10360 SourceName(Identifier {
10361 start: 17,
10362 end: 20,
10363 }))))))),
10364 b"..."
10365 }
10366 b"GV3abc..." => {
10367 SpecialName::Guard(
10368 Name::Unscoped(
10369 UnscopedName::Unqualified(
10370 UnqualifiedName::Source(
10371 SourceName(Identifier {
10372 start: 3,
10373 end: 6,
10374 }))))),
10375 b"..."
10376 }
10377 b"GR3abc_..." => {
10378 SpecialName::GuardTemporary(
10379 Name::Unscoped(
10380 UnscopedName::Unqualified(
10381 UnqualifiedName::Source(
10382 SourceName(Identifier {
10383 start: 3,
10384 end: 6,
10385 })))),
10386 0),
10387 b"..."
10388 }
10389 b"GR3abc0_..." => {
10390 SpecialName::GuardTemporary(
10391 Name::Unscoped(
10392 UnscopedName::Unqualified(
10393 UnqualifiedName::Source(
10394 SourceName(Identifier {
10395 start: 3,
10396 end: 6,
10397 })))),
10398 1),
10399 b"..."
10400 }
10401 b"TCc7_i..." => {
10402 SpecialName::ConstructionVtable(
10403 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)),
10404 7,
10405 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))
10406 ),
10407 b"..."
10408 }
10409 b"TFi..." => {
10410 SpecialName::TypeinfoFunction(
10411 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10412 b"..."
10413 }
10414 b"TH4name..." => {
10415 SpecialName::TlsInit(
10416 Name::Unscoped(
10417 UnscopedName::Unqualified(
10418 UnqualifiedName::Source(
10419 SourceName(Identifier { start: 3, end: 7 }))))),
10420 b"..."
10421 }
10422 b"TW4name..." => {
10423 SpecialName::TlsWrapper(
10424 Name::Unscoped(
10425 UnscopedName::Unqualified(
10426 UnqualifiedName::Source(
10427 SourceName(Identifier { start: 3, end: 7 }))))),
10428 b"..."
10429 }
10430 }
10431 Err => {
10432 b"TZ" => Error::UnexpectedText,
10433 b"GZ" => Error::UnexpectedText,
10434 b"GR3abcz" => Error::UnexpectedText,
10435 b"GR3abc0z" => Error::UnexpectedText,
10436 b"T" => Error::UnexpectedEnd,
10437 b"G" => Error::UnexpectedEnd,
10438 b"" => Error::UnexpectedEnd,
10439 b"GR3abc" => Error::UnexpectedEnd,
10440 b"GR3abc0" => Error::UnexpectedEnd,
10441 // This number is not allowed to be negative.
10442 b"TCcn7_i..." => Error::UnexpectedText,
10443 }
10444 });
10445 }
10446
10447 #[test]
parse_function_param()10448 fn parse_function_param() {
10449 assert_parse!(FunctionParam {
10450 Ok => {
10451 b"fpK_..." => {
10452 FunctionParam(0,
10453 CvQualifiers {
10454 restrict: false,
10455 volatile: false,
10456 const_: true,
10457 },
10458 Some(0)),
10459 b"..."
10460 }
10461 b"fL1pK_..." => {
10462 FunctionParam(1,
10463 CvQualifiers {
10464 restrict: false,
10465 volatile: false,
10466 const_: true,
10467 },
10468 Some(0)),
10469 b"..."
10470 }
10471 b"fpK3_..." => {
10472 FunctionParam(0,
10473 CvQualifiers {
10474 restrict: false,
10475 volatile: false,
10476 const_: true,
10477 },
10478 Some(4)),
10479 b"..."
10480 }
10481 b"fL1pK4_..." => {
10482 FunctionParam(1,
10483 CvQualifiers {
10484 restrict: false,
10485 volatile: false,
10486 const_: true,
10487 },
10488 Some(5)),
10489 b"..."
10490 }
10491 }
10492 Err => {
10493 b"fz" => Error::UnexpectedText,
10494 b"fLp_" => Error::UnexpectedText,
10495 b"fpL_" => Error::UnexpectedText,
10496 b"fL1pK4z" => Error::UnexpectedText,
10497 b"fL1pK4" => Error::UnexpectedEnd,
10498 b"fL1p" => Error::UnexpectedEnd,
10499 b"fL1" => Error::UnexpectedEnd,
10500 b"fL" => Error::UnexpectedEnd,
10501 b"f" => Error::UnexpectedEnd,
10502 b"" => Error::UnexpectedEnd,
10503 }
10504 });
10505 }
10506
10507 #[test]
parse_discriminator()10508 fn parse_discriminator() {
10509 assert_parse!(Discriminator {
10510 Ok => {
10511 b"_0..." => {
10512 Discriminator(0),
10513 b"..."
10514 }
10515 b"_9..." => {
10516 Discriminator(9),
10517 b"..."
10518 }
10519 b"__99_..." => {
10520 Discriminator(99),
10521 b"..."
10522 }
10523 }
10524 Err => {
10525 b"_n1" => Error::UnexpectedText,
10526 b"__99..." => Error::UnexpectedText,
10527 b"__99" => Error::UnexpectedEnd,
10528 b"..." => Error::UnexpectedText,
10529 }
10530 });
10531 }
10532
10533 #[test]
parse_data_member_prefix()10534 fn parse_data_member_prefix() {
10535 assert_parse!(DataMemberPrefix {
10536 Ok => {
10537 b"3fooM..." => {
10538 DataMemberPrefix(SourceName(Identifier {
10539 start: 1,
10540 end: 4,
10541 })),
10542 b"..."
10543 }
10544 }
10545 Err => {
10546 b"zzz" => Error::UnexpectedText,
10547 b"1" => Error::UnexpectedEnd,
10548 b"" => Error::UnexpectedEnd,
10549 }
10550 });
10551 }
10552
10553 #[test]
parse_ref_qualifier()10554 fn parse_ref_qualifier() {
10555 assert_parse!(RefQualifier {
10556 Ok => {
10557 b"R..." => {
10558 RefQualifier::LValueRef,
10559 b"..."
10560 }
10561 b"O..." => {
10562 RefQualifier::RValueRef,
10563 b"..."
10564 }
10565 }
10566 Err => {
10567 b"..." => Error::UnexpectedText,
10568 b"" => Error::UnexpectedEnd,
10569 }
10570 });
10571 }
10572
10573 #[test]
parse_cv_qualifiers()10574 fn parse_cv_qualifiers() {
10575 assert_parse!(CvQualifiers {
10576 Ok => {
10577 b"" => {
10578 CvQualifiers { restrict: false, volatile: false, const_: false },
10579 b""
10580 }
10581 b"..." => {
10582 CvQualifiers { restrict: false, volatile: false, const_: false },
10583 b"..."
10584 }
10585 b"r..." => {
10586 CvQualifiers { restrict: true, volatile: false, const_: false },
10587 b"..."
10588 }
10589 b"rV..." => {
10590 CvQualifiers { restrict: true, volatile: true, const_: false },
10591 b"..."
10592 }
10593 b"rVK..." => {
10594 CvQualifiers { restrict: true, volatile: true, const_: true },
10595 b"..."
10596 }
10597 b"V" => {
10598 CvQualifiers { restrict: false, volatile: true, const_: false },
10599 b""
10600 }
10601 b"VK" => {
10602 CvQualifiers { restrict: false, volatile: true, const_: true },
10603 b""
10604 }
10605 b"K..." => {
10606 CvQualifiers { restrict: false, volatile: false, const_: true },
10607 b"..."
10608 }
10609 }
10610 Err => {
10611 // None.
10612 }
10613 });
10614 }
10615
10616 #[test]
parse_builtin_type()10617 fn parse_builtin_type() {
10618 assert_parse!(BuiltinType {
10619 Ok => {
10620 b"c..." => {
10621 BuiltinType::Standard(StandardBuiltinType::Char),
10622 b"..."
10623 }
10624 b"c" => {
10625 BuiltinType::Standard(StandardBuiltinType::Char),
10626 b""
10627 }
10628 b"u3abc..." => {
10629 BuiltinType::Extension(SourceName(Identifier {
10630 start: 2,
10631 end: 5,
10632 })),
10633 b"..."
10634 }
10635 }
10636 Err => {
10637 b"." => Error::UnexpectedText,
10638 b"" => Error::UnexpectedEnd,
10639 }
10640 });
10641 }
10642
10643 #[test]
parse_template_param()10644 fn parse_template_param() {
10645 assert_parse!(TemplateParam {
10646 Ok => {
10647 b"T_..." => {
10648 TemplateParam(0),
10649 b"..."
10650 }
10651 b"T3_..." => {
10652 TemplateParam(4),
10653 b"..."
10654 }
10655 }
10656 Err => {
10657 b"wtf" => Error::UnexpectedText,
10658 b"Twtf" => Error::UnexpectedText,
10659 b"T3wtf" => Error::UnexpectedText,
10660 b"T" => Error::UnexpectedEnd,
10661 b"T3" => Error::UnexpectedEnd,
10662 b"" => Error::UnexpectedEnd,
10663 }
10664 });
10665 }
10666
10667 #[test]
parse_unscoped_name()10668 fn parse_unscoped_name() {
10669 assert_parse!(UnscopedName {
10670 Ok => {
10671 b"St5hello..." => {
10672 UnscopedName::Std(UnqualifiedName::Source(SourceName(Identifier {
10673 start: 3,
10674 end: 8,
10675 }))),
10676 b"..."
10677 }
10678 b"5hello..." => {
10679 UnscopedName::Unqualified(UnqualifiedName::Source(SourceName(Identifier {
10680 start: 1,
10681 end: 6,
10682 }))),
10683 b"..."
10684 }
10685 }
10686 Err => {
10687 b"St..." => Error::UnexpectedText,
10688 b"..." => Error::UnexpectedText,
10689 b"" => Error::UnexpectedEnd,
10690 }
10691 });
10692 }
10693
10694 #[test]
parse_unqualified_name()10695 fn parse_unqualified_name() {
10696 assert_parse!(UnqualifiedName {
10697 Ok => {
10698 b"qu.." => {
10699 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::Question)),
10700 b".."
10701 }
10702 b"C1.." => {
10703 UnqualifiedName::CtorDtor(CtorDtorName::CompleteConstructor(None)),
10704 b".."
10705 }
10706 b"10abcdefghij..." => {
10707 UnqualifiedName::Source(SourceName(Identifier {
10708 start: 2,
10709 end: 12,
10710 })),
10711 b"..."
10712 }
10713 b"UllE_..." => {
10714 UnqualifiedName::ClosureType(
10715 ClosureTypeName(
10716 LambdaSig(vec![
10717 TypeHandle::Builtin(
10718 BuiltinType::Standard(
10719 StandardBuiltinType::Long))
10720 ]),
10721 None)),
10722 b"..."
10723 }
10724 b"Ut5_..." => {
10725 UnqualifiedName::UnnamedType(UnnamedTypeName(Some(5))),
10726 b"..."
10727 }
10728 b"B5cxx11..." => {
10729 UnqualifiedName::ABITag(TaggedName(SourceName(Identifier {
10730 start: 2,
10731 end: 7,
10732 }))),
10733 b"..."
10734 }
10735 b"L3foo_0..." => {
10736 UnqualifiedName::LocalSourceName(
10737 SourceName(Identifier {
10738 start: 2,
10739 end: 5
10740 }),
10741 Some(Discriminator(0))
10742 ),
10743 "..."
10744 }
10745 b"L3foo..." => {
10746 UnqualifiedName::LocalSourceName(
10747 SourceName(Identifier {
10748 start: 2,
10749 end: 5
10750 }),
10751 None
10752 ),
10753 "..."
10754 }
10755 }
10756 Err => {
10757 b"zzz" => Error::UnexpectedText,
10758 b"Uq" => Error::UnexpectedText,
10759 b"C" => Error::UnexpectedEnd,
10760 b"" => Error::UnexpectedEnd,
10761 }
10762 });
10763 }
10764
10765 #[test]
parse_unnamed_type_name()10766 fn parse_unnamed_type_name() {
10767 assert_parse!(UnnamedTypeName {
10768 Ok => {
10769 b"Ut_abc" => {
10770 UnnamedTypeName(None),
10771 b"abc"
10772 }
10773 b"Ut42_abc" => {
10774 UnnamedTypeName(Some(42)),
10775 b"abc"
10776 }
10777 b"Ut42_" => {
10778 UnnamedTypeName(Some(42)),
10779 b""
10780 }
10781 }
10782 Err => {
10783 b"ut_" => Error::UnexpectedText,
10784 b"u" => Error::UnexpectedEnd,
10785 b"Ut" => Error::UnexpectedEnd,
10786 b"Ut._" => Error::UnexpectedText,
10787 b"Ut42" => Error::UnexpectedEnd,
10788 }
10789 });
10790 }
10791
10792 #[test]
parse_identifier()10793 fn parse_identifier() {
10794 assert_parse!(Identifier {
10795 Ok => {
10796 b"1abc" => {
10797 Identifier { start: 0, end: 4 },
10798 b""
10799 }
10800 b"_Az1\0\0\0" => {
10801 Identifier { start: 0, end: 4 },
10802 b"\0\0\0"
10803 }
10804 b"$_0\0\0\0" => {
10805 Identifier { start: 0, end: 3 },
10806 b"\0\0\0"
10807 }
10808 }
10809 Err => {
10810 b"\0\0\0" => Error::UnexpectedText,
10811 b"" => Error::UnexpectedEnd,
10812 }
10813 });
10814 }
10815
10816 #[test]
parse_source_name()10817 fn parse_source_name() {
10818 assert_parse!(SourceName {
10819 Ok => {
10820 b"1abc" => {
10821 SourceName(Identifier { start: 1, end: 2 }),
10822 b"bc"
10823 }
10824 b"10abcdefghijklm" => {
10825 SourceName(Identifier { start: 2, end: 12 }),
10826 b"klm"
10827 }
10828 }
10829 Err => {
10830 b"0abc" => Error::UnexpectedText,
10831 b"n1abc" => Error::UnexpectedText,
10832 b"10abcdef" => Error::UnexpectedEnd,
10833 b"" => Error::UnexpectedEnd,
10834 }
10835 });
10836 }
10837
10838 #[test]
parse_number()10839 fn parse_number() {
10840 assert_parse!(Number {
10841 Ok => {
10842 b"n2n3" => {
10843 -2,
10844 b"n3"
10845 }
10846 b"12345abcdef" => {
10847 12345,
10848 b"abcdef"
10849 }
10850 b"0abcdef" => {
10851 0,
10852 b"abcdef"
10853 }
10854 b"42" => {
10855 42,
10856 b""
10857 }
10858 }
10859 Err => {
10860 b"001" => Error::UnexpectedText,
10861 b"wutang" => Error::UnexpectedText,
10862 b"n" => Error::UnexpectedEnd,
10863 b"" => Error::UnexpectedEnd,
10864 }
10865 });
10866 }
10867
10868 #[test]
parse_call_offset()10869 fn parse_call_offset() {
10870 assert_parse!(CallOffset {
10871 Ok => {
10872 b"hn42_..." => {
10873 CallOffset::NonVirtual(NvOffset(-42)),
10874 b"..."
10875 }
10876 b"vn42_36_..." => {
10877 CallOffset::Virtual(VOffset(-42, 36)),
10878 b"..."
10879 }
10880 }
10881 Err => {
10882 b"h1..." => Error::UnexpectedText,
10883 b"v1_1..." => Error::UnexpectedText,
10884 b"hh" => Error::UnexpectedText,
10885 b"vv" => Error::UnexpectedText,
10886 b"z" => Error::UnexpectedText,
10887 b"" => Error::UnexpectedEnd,
10888 }
10889 });
10890 }
10891
10892 #[test]
parse_v_offset()10893 fn parse_v_offset() {
10894 assert_parse!(VOffset {
10895 Ok => {
10896 b"n2_n3abcdef" => {
10897 VOffset(-2, -3),
10898 b"abcdef"
10899 }
10900 b"12345_12345abcdef" => {
10901 VOffset(12345, 12345),
10902 b"abcdef"
10903 }
10904 b"0_0abcdef" => {
10905 VOffset(0, 0),
10906 b"abcdef"
10907 }
10908 b"42_n3" => {
10909 VOffset(42, -3),
10910 b""
10911 }
10912 }
10913 Err => {
10914 b"001" => Error::UnexpectedText,
10915 b"1_001" => Error::UnexpectedText,
10916 b"wutang" => Error::UnexpectedText,
10917 b"n_" => Error::UnexpectedText,
10918 b"1_n" => Error::UnexpectedEnd,
10919 b"1_" => Error::UnexpectedEnd,
10920 b"n" => Error::UnexpectedEnd,
10921 b"" => Error::UnexpectedEnd,
10922 }
10923 });
10924 }
10925
10926 #[test]
parse_nv_offset()10927 fn parse_nv_offset() {
10928 assert_parse!(NvOffset {
10929 Ok => {
10930 b"n2n3" => {
10931 NvOffset(-2),
10932 b"n3"
10933 }
10934 b"12345abcdef" => {
10935 NvOffset(12345),
10936 b"abcdef"
10937 }
10938 b"0abcdef" => {
10939 NvOffset(0),
10940 b"abcdef"
10941 }
10942 b"42" => {
10943 NvOffset(42),
10944 b""
10945 }
10946 }
10947 Err => {
10948 b"001" => Error::UnexpectedText,
10949 b"wutang" => Error::UnexpectedText,
10950 b"" => Error::UnexpectedEnd,
10951 }
10952 });
10953 }
10954
10955 #[test]
parse_seq_id()10956 fn parse_seq_id() {
10957 assert_parse!(SeqId {
10958 Ok => {
10959 b"1_" => {
10960 SeqId(1),
10961 b"_"
10962 }
10963 b"42" => {
10964 SeqId(146),
10965 b""
10966 }
10967 b"ABCabc" => {
10968 SeqId(13368),
10969 b"abc"
10970 }
10971 }
10972 Err => {
10973 b"abc" => Error::UnexpectedText,
10974 b"001" => Error::UnexpectedText,
10975 b"wutang" => Error::UnexpectedText,
10976 b"" => Error::UnexpectedEnd,
10977 }
10978 });
10979 }
10980
10981 #[test]
parse_ctor_dtor_name()10982 fn parse_ctor_dtor_name() {
10983 assert_parse!(CtorDtorName {
10984 Ok => {
10985 b"D0" => {
10986 CtorDtorName::DeletingDestructor,
10987 b""
10988 }
10989 b"C101" => {
10990 CtorDtorName::CompleteConstructor(None),
10991 b"01"
10992 }
10993 }
10994 Err => {
10995 b"gayagaya" => Error::UnexpectedText,
10996 b"C" => Error::UnexpectedEnd,
10997 b"" => Error::UnexpectedEnd,
10998 }
10999 });
11000 }
11001
11002 #[test]
parse_operator_name()11003 fn parse_operator_name() {
11004 assert_parse!(OperatorName {
11005 Ok => {
11006 b"qu..." => {
11007 OperatorName::Simple(SimpleOperatorName::Question),
11008 b"..."
11009 }
11010 b"cvi..." => {
11011 OperatorName::Conversion(
11012 TypeHandle::Builtin(
11013 BuiltinType::Standard(
11014 StandardBuiltinType::Int))),
11015 b"..."
11016 }
11017 b"li3Foo..." => {
11018 OperatorName::Literal(SourceName(Identifier {
11019 start: 3,
11020 end: 6,
11021 })),
11022 b"..."
11023 }
11024 b"v33Foo..." => {
11025 OperatorName::VendorExtension(3, SourceName(Identifier {
11026 start: 3,
11027 end: 6
11028 })),
11029 b"..."
11030 }
11031 }
11032 Err => {
11033 b"cv" => Error::UnexpectedEnd,
11034 b"li3ab" => Error::UnexpectedEnd,
11035 b"li" => Error::UnexpectedEnd,
11036 b"v33ab" => Error::UnexpectedEnd,
11037 b"v3" => Error::UnexpectedEnd,
11038 b"v" => Error::UnexpectedEnd,
11039 b"" => Error::UnexpectedEnd,
11040 b"q" => Error::UnexpectedText,
11041 b"c" => Error::UnexpectedText,
11042 b"l" => Error::UnexpectedText,
11043 b"zzz" => Error::UnexpectedText,
11044 }
11045 });
11046 }
11047
11048 #[test]
parse_simple_operator_name()11049 fn parse_simple_operator_name() {
11050 assert_parse!(SimpleOperatorName {
11051 Ok => {
11052 b"qu" => {
11053 SimpleOperatorName::Question,
11054 b""
11055 }
11056 b"quokka" => {
11057 SimpleOperatorName::Question,
11058 b"okka"
11059 }
11060 }
11061 Err => {
11062 b"bu-buuuu" => Error::UnexpectedText,
11063 b"q" => Error::UnexpectedEnd,
11064 b"" => Error::UnexpectedEnd,
11065 }
11066 });
11067 }
11068 }
11069