1 //! Abstract syntax tree types for mangled symbols.
2
3 use super::{DemangleNodeType, DemangleOptions, DemangleWrite, ParseOptions};
4 use boxed::Box;
5 use error::{self, Result};
6 use index_str::IndexStr;
7 use std::cell::Cell;
8 #[cfg(feature = "logging")]
9 use std::cell::RefCell;
10 use std::fmt::{self, Write};
11 use std::hash::{Hash, Hasher};
12 use std::mem;
13 use std::ops;
14 use std::ptr;
15 use string::String;
16 use subs::{Substitutable, SubstitutionTable};
17 use vec::Vec;
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 input.len(),
41 );
42 *depth.borrow_mut() += 1;
43 });
44 AutoLogParse
45 }
46
47 #[cfg(not(feature = "logging"))]
48 #[inline(always)]
new(_: &'static str, _: IndexStr) -> AutoLogParse49 fn new(_: &'static str, _: IndexStr) -> AutoLogParse {
50 AutoLogParse
51 }
52 }
53
54 #[cfg(feature = "logging")]
55 impl Drop for AutoLogParse {
drop(&mut self)56 fn drop(&mut self) {
57 LOG_DEPTH.with(|depth| {
58 *depth.borrow_mut() -= 1;
59 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
60 log!("{})", indent);
61 });
62 }
63 }
64
65 /// Performs the two operations that begin every parse:
66 ///
67 /// 1. Keeps track of recursion levels and early returns with an error if there
68 /// is too much recursion.
69 ///
70 /// 2. Automatically log start and end parsing in an s-expression format, when the
71 /// `logging` feature is enabled.
72 macro_rules! try_begin_parse {
73 ( $production:expr , $ctx:expr , $input:expr ) => {
74 let _log = AutoLogParse::new($production, $input);
75 let _auto_check_recursion = AutoParseRecursion::new($ctx)?;
76 };
77 }
78
79 struct AutoLogDemangle;
80
81 impl AutoLogDemangle {
82 #[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,83 fn new<P, W>(
84 production: &P,
85 ctx: &DemangleContext<W>,
86 scope: Option<ArgScopeStack>,
87 is_inner: bool,
88 ) -> AutoLogDemangle
89 where
90 P: ?Sized + fmt::Debug,
91 W: DemangleWrite,
92 {
93 LOG_DEPTH.with(|depth| {
94 if *depth.borrow() == 0 {
95 println!();
96 }
97
98 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
99 log!("{}(", indent);
100 log!(
101 "{} {}{:?}",
102 indent,
103 if is_inner { "as_inner: " } else { "" },
104 production
105 );
106 log!("{} inner = {:?}", indent, ctx.inner);
107 log!("{} scope = {:?}", indent, scope);
108
109 *depth.borrow_mut() += 1;
110 });
111 AutoLogDemangle
112 }
113
114 #[cfg(not(feature = "logging"))]
115 #[inline(always)]
new<P, W>( _: &P, _: &DemangleContext<W>, _: Option<ArgScopeStack>, _: bool, ) -> AutoLogDemangle where P: ?Sized + fmt::Debug, W: DemangleWrite,116 fn new<P, W>(
117 _: &P,
118 _: &DemangleContext<W>,
119 _: Option<ArgScopeStack>,
120 _: bool,
121 ) -> AutoLogDemangle
122 where
123 P: ?Sized + fmt::Debug,
124 W: DemangleWrite,
125 {
126 AutoLogDemangle
127 }
128 }
129
130 #[cfg(feature = "logging")]
131 impl Drop for AutoLogDemangle {
drop(&mut self)132 fn drop(&mut self) {
133 LOG_DEPTH.with(|depth| {
134 *depth.borrow_mut() -= 1;
135 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
136 log!("{})", indent);
137 });
138 }
139 }
140
141 /// Automatically log start and end demangling in an s-expression format, when
142 /// the `logging` feature is enabled.
143 macro_rules! try_begin_demangle {
144 ( $production:expr, $ctx:expr, $scope:expr ) => {{
145 let _log = AutoLogDemangle::new($production, $ctx, $scope, false);
146 &mut AutoParseDemangle::new($ctx)?
147 }};
148 }
149
150 /// Automatically log start and end demangling in an s-expression format, when
151 /// the `logging` feature is enabled.
152 macro_rules! try_begin_demangle_as_inner {
153 ( $production:expr, $ctx:expr, $scope:expr ) => {{
154 let _log = AutoLogDemangle::new($production, $ctx, $scope, true);
155 &mut AutoParseDemangle::new($ctx)?
156 }};
157 }
158
159 #[derive(Debug, Default, Clone, Copy)]
160 struct ParseContextState {
161 // The current recursion level. Should always be less than or equal to the
162 // maximum.
163 recursion_level: u32,
164 // Whether or not we are currently parsing a conversion operator.
165 in_conversion: bool,
166 }
167
168 /// Common context needed when parsing.
169 #[derive(Debug, Clone)]
170 pub struct ParseContext {
171 // Maximum amount of recursive parsing calls we will allow. If this is too
172 // large, we can blow the stack.
173 max_recursion: u32,
174 // Mutable state within the `ParseContext`.
175 state: Cell<ParseContextState>,
176 }
177
178 impl ParseContext {
179 /// Construct a new `ParseContext`.
new(options: ParseOptions) -> ParseContext180 pub fn new(options: ParseOptions) -> ParseContext {
181 ParseContext {
182 max_recursion: options.recursion_limit.map(|v| v.get()).unwrap_or(96),
183 state: Cell::new(ParseContextState::default()),
184 }
185 }
186
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)
344 -> Result<(&'ctx TemplateArg, &'ctx TemplateArgs)>;
345
346 /// Get the current scope's `index`th function argument's type.
get_function_arg(&'me self, index: usize) -> Result<&'ctx Type>347 fn get_function_arg(&'me self, index: usize) -> Result<&'ctx Type>;
348 }
349
350 /// An `ArgScopeStack` represents the current function and template demangling
351 /// scope we are within. As we enter new demangling scopes, we construct new
352 /// `ArgScopeStack`s whose `prev` references point back to the old ones. These
353 /// `ArgScopeStack`s are kept on the native stack, and as functions return, they
354 /// go out of scope and we use the previous `ArgScopeStack`s again.
355 #[derive(Copy, Clone, Debug)]
356 pub struct ArgScopeStack<'prev, 'subs>
357 where
358 'subs: 'prev,
359 {
360 item: &'subs dyn ArgScope<'subs, 'subs>,
361 in_arg: Option<(usize, &'subs TemplateArgs)>,
362 prev: Option<&'prev ArgScopeStack<'prev, 'subs>>,
363 }
364
365 /// When we first begin demangling, we haven't entered any function or template
366 /// demangling scope and we don't have any useful `ArgScopeStack`. Therefore, we
367 /// are never actually dealing with `ArgScopeStack` directly in practice, but
368 /// always an `Option<ArgScopeStack>` instead. Nevertheless, we want to define
369 /// useful methods on `Option<ArgScopeStack>`.
370 ///
371 /// A custom "extension" trait with exactly one implementor: Rust's principled
372 /// monkey patching!
373 trait ArgScopeStackExt<'prev, 'subs>: Copy {
374 /// Push a new `ArgScope` onto this `ArgScopeStack` and return the new
375 /// `ArgScopeStack` with the pushed resolver on top.
push( &'prev self, item: &'subs dyn ArgScope<'subs, 'subs>, ) -> Option<ArgScopeStack<'prev, 'subs>>376 fn push(
377 &'prev self,
378 item: &'subs dyn ArgScope<'subs, 'subs>,
379 ) -> Option<ArgScopeStack<'prev, 'subs>>;
380 }
381
382 impl<'prev, 'subs> ArgScopeStackExt<'prev, 'subs> for Option<ArgScopeStack<'prev, 'subs>> {
push( &'prev self, item: &'subs dyn ArgScope<'subs, 'subs>, ) -> Option<ArgScopeStack<'prev, 'subs>>383 fn push(
384 &'prev self,
385 item: &'subs dyn ArgScope<'subs, 'subs>,
386 ) -> Option<ArgScopeStack<'prev, 'subs>> {
387 log!("ArgScopeStack::push: {:?}", item);
388 Some(ArgScopeStack {
389 prev: self.as_ref(),
390 in_arg: None,
391 item: item,
392 })
393 }
394 }
395
396 /// A stack of `ArgScope`s is itself an `ArgScope`!
397 impl<'prev, 'subs> ArgScope<'prev, 'subs> for Option<ArgScopeStack<'prev, 'subs>> {
leaf_name(&'prev self) -> Result<LeafName<'subs>>398 fn leaf_name(&'prev self) -> Result<LeafName<'subs>> {
399 let mut scope = self.as_ref();
400 while let Some(s) = scope {
401 if let Ok(c) = s.item.leaf_name() {
402 return Ok(c);
403 }
404 scope = s.prev;
405 }
406 Err(error::Error::BadLeafNameReference)
407 }
408
get_template_arg( &'prev self, idx: usize, ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)>409 fn get_template_arg(
410 &'prev self,
411 idx: usize,
412 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
413 let mut scope = self.as_ref();
414 while let Some(s) = scope {
415 if let Ok((arg, args)) = s.item.get_template_arg(idx) {
416 if let Some((in_idx, in_args)) = s.in_arg {
417 if args as *const TemplateArgs == in_args as *const TemplateArgs
418 && in_idx <= idx
419 {
420 return Err(error::Error::ForwardTemplateArgReference);
421 }
422 }
423 return Ok((arg, args));
424 }
425 scope = s.prev;
426 }
427
428 Err(error::Error::BadTemplateArgReference)
429 }
430
get_function_arg(&'prev self, idx: usize) -> Result<&'subs Type>431 fn get_function_arg(&'prev self, idx: usize) -> Result<&'subs Type> {
432 let mut scope = self.as_ref();
433 while let Some(s) = scope {
434 if let Ok(arg) = s.item.get_function_arg(idx) {
435 return Ok(arg);
436 }
437 scope = s.prev;
438 }
439
440 Err(error::Error::BadFunctionArgReference)
441 }
442 }
443
444 #[derive(Debug, Copy, Clone)]
445 struct DemangleState {
446 /// How deep in the demangling are we?
447 pub recursion_level: u32,
448 }
449
450 /// An RAII type to automatically check the recursion level against the
451 /// maximum. If the maximum has been crossed, return an error. Otherwise,
452 /// increment the level upon construction, and decrement it upon destruction.
453 struct AutoParseDemangle<'a, 'b, W: 'a + DemangleWrite>(&'b mut DemangleContext<'a, W>);
454
455 impl<'a, 'b, W: 'a + DemangleWrite> AutoParseDemangle<'a, 'b, W> {
456 #[inline]
new(ctx: &'b mut DemangleContext<'a, W>) -> std::result::Result<Self, fmt::Error>457 fn new(ctx: &'b mut DemangleContext<'a, W>) -> std::result::Result<Self, fmt::Error> {
458 ctx.enter_recursion()?;
459 Ok(AutoParseDemangle(ctx))
460 }
461 }
462
463 impl<'a, 'b, W: 'a + DemangleWrite> std::ops::Deref for AutoParseDemangle<'a, 'b, W> {
464 type Target = DemangleContext<'a, W>;
465
deref(&self) -> &Self::Target466 fn deref(&self) -> &Self::Target {
467 self.0
468 }
469 }
470
471 impl<'a, 'b, W: 'a + DemangleWrite> std::ops::DerefMut for AutoParseDemangle<'a, 'b, W> {
deref_mut(&mut self) -> &mut Self::Target472 fn deref_mut(&mut self) -> &mut Self::Target {
473 self.0
474 }
475 }
476
477 impl<'a, 'b, W: 'a + DemangleWrite> Drop for AutoParseDemangle<'a, 'b, W> {
478 #[inline]
drop(&mut self)479 fn drop(&mut self) {
480 self.0.exit_recursion();
481 }
482 }
483
484 /// Common state that is required when demangling a mangled symbol's parsed AST.
485 #[doc(hidden)]
486 #[derive(Debug)]
487 pub struct DemangleContext<'a, W>
488 where
489 W: 'a + DemangleWrite,
490 {
491 // The substitution table built up when parsing the mangled symbol into an
492 // AST.
493 subs: &'a SubstitutionTable,
494
495 // The maximum recursion
496 max_recursion: u32,
497
498 // Sometimes an AST node needs to insert itself as an inner item within one
499 // of its children when demangling that child. For example, the AST
500 //
501 // (array 10 int)
502 //
503 // is demangled as `int[10]`, but if we were to demangle the AST
504 //
505 // (lvalue-ref (array 10 int))
506 //
507 // then we would want this demangled form: `int (&) [10]`, which requires
508 // the parent lvalue-ref to be passed into the child array's demangling
509 // method. This kind of thing also pops up with function pointers.
510 //
511 // The `inner` stack enables such behavior by allowing us to pass AST
512 // parents down to their children as inner items.
513 inner: Vec<&'a dyn DemangleAsInner<'a, W>>,
514
515 // The original input string.
516 input: &'a [u8],
517
518 // `Identifier`s will be placed here, so `UnnamedTypeName` can utilize and print
519 // out the Constructor/Destructor used.
520 source_name: Option<&'a str>,
521
522 // What the demangled name is being written to.
523 out: &'a mut W,
524
525 // The total number of bytes written to `out`. This is maintained by the
526 // `Write` implementation for `DemangleContext`.
527 bytes_written: usize,
528
529 // The last char written to `out`, if any.
530 last_char_written: Option<char>,
531
532 // We are currently demangling a lambda argument, so template substitution
533 // should be suppressed to match libiberty.
534 is_lambda_arg: bool,
535
536 // We are currently demangling a template-prefix.
537 is_template_prefix: bool,
538
539 // We are currently demangling a template-prefix in a nested-name.
540 is_template_prefix_in_nested_name: bool,
541
542 // `PackExpansion`'s should only print '...', only when there is no template
543 // argument pack.
544 is_template_argument_pack: bool,
545
546 // Whether to show function parameters.
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_params: bool,
550
551 // Whether to show function return types.
552 // This must be set to true before calling `demangle` on `Encoding`
553 // unless that call is via the toplevel call to `MangledName::demangle`.
554 show_return_type: bool,
555
556 // recursion protection.
557 state: Cell<DemangleState>,
558 }
559
560 impl<'a, W> fmt::Write for DemangleContext<'a, W>
561 where
562 W: 'a + DemangleWrite,
563 {
write_str(&mut self, s: &str) -> fmt::Result564 fn write_str(&mut self, s: &str) -> fmt::Result {
565 if s.is_empty() {
566 return Ok(());
567 }
568
569 log!("DemangleContext::write: '{}'", s);
570
571 self.out.write_string(s).map(|_| {
572 self.last_char_written = s.chars().last();
573 self.bytes_written += s.len();
574 })
575 }
576 }
577
578 impl<'a, W> DemangleContext<'a, W>
579 where
580 W: 'a + DemangleWrite,
581 {
582 /// Construct a new `DemangleContext`.
new( subs: &'a SubstitutionTable, input: &'a [u8], options: DemangleOptions, out: &'a mut W, ) -> DemangleContext<'a, W>583 pub fn new(
584 subs: &'a SubstitutionTable,
585 input: &'a [u8],
586 options: DemangleOptions,
587 out: &'a mut W,
588 ) -> DemangleContext<'a, W> {
589 DemangleContext {
590 subs: subs,
591 max_recursion: options.recursion_limit.map(|v| v.get()).unwrap_or(128),
592 inner: vec![],
593 input: input,
594 source_name: None,
595 out: out,
596 bytes_written: 0,
597 last_char_written: None,
598 is_lambda_arg: false,
599 is_template_prefix: false,
600 is_template_prefix_in_nested_name: false,
601 is_template_argument_pack: false,
602 show_params: !options.no_params,
603 show_return_type: !options.no_return_type,
604 state: Cell::new(DemangleState { recursion_level: 0 }),
605 }
606 }
607
608 /// Get the current recursion level for this context.
recursion_level(&self) -> u32609 pub fn recursion_level(&self) -> u32 {
610 self.state.get().recursion_level
611 }
612
613 #[inline]
enter_recursion(&self) -> fmt::Result614 fn enter_recursion(&self) -> fmt::Result {
615 let mut state = self.state.get();
616 let new_recursion_level = state.recursion_level + 1;
617
618 if new_recursion_level >= self.max_recursion {
619 log!("Hit too much recursion at level {}", self.max_recursion);
620 Err(Default::default())
621 } else {
622 state.recursion_level = new_recursion_level;
623 self.state.set(state);
624 Ok(())
625 }
626 }
627
628 #[inline]
exit_recursion(&self)629 fn exit_recursion(&self) {
630 let mut state = self.state.get();
631 debug_assert!(state.recursion_level >= 1);
632 state.recursion_level -= 1;
633 self.state.set(state);
634 }
635
636 #[inline]
ensure(&mut self, ch: char) -> fmt::Result637 fn ensure(&mut self, ch: char) -> fmt::Result {
638 if self.last_char_written == Some(ch) {
639 Ok(())
640 } else {
641 write!(self, "{}", ch)?;
642 Ok(())
643 }
644 }
645
646 #[inline]
ensure_space(&mut self) -> fmt::Result647 fn ensure_space(&mut self) -> fmt::Result {
648 self.ensure(' ')
649 }
650
651 #[inline]
push_inner(&mut self, item: &'a dyn DemangleAsInner<'a, W>)652 fn push_inner(&mut self, item: &'a dyn DemangleAsInner<'a, W>) {
653 log!("DemangleContext::push_inner: {:?}", item);
654 self.inner.push(item);
655 }
656
657 #[inline]
pop_inner(&mut self) -> Option<&'a dyn DemangleAsInner<'a, W>>658 fn pop_inner(&mut self) -> Option<&'a dyn DemangleAsInner<'a, W>> {
659 let popped = self.inner.pop();
660 log!("DemangleContext::pop_inner: {:?}", popped);
661 popped
662 }
663
664 #[inline]
pop_inner_if(&mut self, inner: &'a dyn DemangleAsInner<'a, W>) -> bool665 fn pop_inner_if(&mut self, inner: &'a dyn DemangleAsInner<'a, W>) -> bool {
666 let last = match self.inner.last() {
667 None => return false,
668 Some(last) => *last,
669 };
670
671 if ptr::eq(last, inner) {
672 self.inner.pop();
673 true
674 } else {
675 false
676 }
677 }
678
demangle_inner_prefixes<'prev>( &mut self, scope: Option<ArgScopeStack<'prev, 'a>>, ) -> fmt::Result679 fn demangle_inner_prefixes<'prev>(
680 &mut self,
681 scope: Option<ArgScopeStack<'prev, 'a>>,
682 ) -> fmt::Result {
683 log!("DemangleContext::demangle_inner_prefixes");
684 let mut new_inner = vec![];
685 while let Some(inner) = self.pop_inner() {
686 if inner
687 .downcast_to_function_type()
688 .map_or(false, |f| !f.cv_qualifiers.is_empty())
689 {
690 log!(
691 "DemangleContext::demangle_inner_prefixes: not a prefix, saving: {:?}",
692 inner
693 );
694 new_inner.push(inner);
695 } else {
696 log!(
697 "DemangleContext::demangle_inner_prefixes: demangling prefix: {:?}",
698 inner
699 );
700 inner.demangle_as_inner(self, scope)?;
701 }
702 }
703 new_inner.reverse();
704 self.inner = new_inner;
705 Ok(())
706 }
707
demangle_inners<'prev>(&mut self, scope: Option<ArgScopeStack<'prev, 'a>>) -> fmt::Result708 fn demangle_inners<'prev>(&mut self, scope: Option<ArgScopeStack<'prev, 'a>>) -> 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!(
913 "Dropping implies we dereferenced and took ownership, which \
914 is not safe for this newtype"
915 );
916 }
917 }
918
919 impl ops::Deref for $newtype_name {
920 type Target = $oldtype;
921
922 fn deref(&self) -> &Self::Target {
923 &self.0
924 }
925 }
926 };
927 }
928
929 // We can't implement `DemangleAsInner` for newtypes of `[TypeHandle]` like we
930 // want to because it is unsized and we need to make trait objects out of
931 // `DemangleAsInner` for pushing onto the context's inner stack. Therefore, we
932 // have this inelegant newtyping of `Vec<TypeHandle>`.
933
934 // A set of function arguments.
935 reference_newtype!(FunctionArgList, Vec<TypeHandle>);
936
937 // A set of function arguments prefixed by a return type (which we want to
938 // ignore).
939 reference_newtype!(FunctionArgListAndReturnType, Vec<TypeHandle>);
940
941 // A newtype around a slice of type handles that we format as function
942 // arguments.
943 reference_newtype!(FunctionArgSlice, [TypeHandle]);
944
945 // Demangle a slice of TypeHandle as a function argument list.
946 impl<'subs, W> Demangle<'subs, W> for FunctionArgSlice
947 where
948 W: 'subs + DemangleWrite,
949 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result950 fn demangle<'prev, 'ctx>(
951 &'subs self,
952 ctx: &'ctx mut DemangleContext<'subs, W>,
953 scope: Option<ArgScopeStack<'prev, 'subs>>,
954 ) -> fmt::Result {
955 let ctx = try_begin_demangle!(self, ctx, scope);
956
957 let mut saw_needs_paren = false;
958 let (needs_space, needs_paren) = ctx
959 .inner
960 .iter()
961 .rev()
962 .map(|inner| {
963 if inner.downcast_to_pointer_to_member().is_some() {
964 (true, true)
965 } else {
966 match inner.downcast_to_type() {
967 Some(&Type::Qualified(..))
968 | Some(&Type::Complex(_))
969 | Some(&Type::Imaginary(_))
970 | Some(&Type::PointerToMember(_)) => (true, true),
971 Some(&Type::PointerTo(_))
972 | Some(&Type::LvalueRef(_))
973 | Some(&Type::RvalueRef(_)) => (false, true),
974 _ => (false, false),
975 }
976 }
977 })
978 .take_while(|&(_, needs_paren)| {
979 if saw_needs_paren {
980 false
981 } else {
982 saw_needs_paren |= needs_paren;
983 true
984 }
985 })
986 .fold(
987 (false, false),
988 |(space, paren), (next_space, next_paren)| {
989 (space || next_space, paren || next_paren)
990 },
991 );
992
993 if needs_paren {
994 let needs_space = needs_space
995 || match ctx.last_char_written {
996 Some('(') | Some('*') => false,
997 _ => true,
998 };
999
1000 if needs_space {
1001 ctx.ensure_space()?;
1002 }
1003
1004 write!(ctx, "(")?;
1005 }
1006
1007 ctx.demangle_inner_prefixes(scope)?;
1008
1009 if needs_paren {
1010 write!(ctx, ")")?;
1011 }
1012
1013 write!(ctx, "(")?;
1014
1015 // To maintain compatibility with libiberty, print `()` instead of
1016 // `(void)` for functions that take no arguments.
1017 if self.len() == 1 && self[0].is_void() {
1018 write!(ctx, ")")?;
1019 return Ok(());
1020 }
1021
1022 let mut need_comma = false;
1023 for arg in self.iter() {
1024 if need_comma {
1025 write!(ctx, ", ")?;
1026 }
1027 arg.demangle(ctx, scope)?;
1028 need_comma = true;
1029 }
1030
1031 write!(ctx, ")")?;
1032
1033 ctx.demangle_inners(scope)
1034 }
1035 }
1036
1037 impl<'subs, W> Demangle<'subs, W> for FunctionArgList
1038 where
1039 W: 'subs + DemangleWrite,
1040 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1041 fn demangle<'prev, 'ctx>(
1042 &'subs self,
1043 ctx: &'ctx mut DemangleContext<'subs, W>,
1044 scope: Option<ArgScopeStack<'prev, 'subs>>,
1045 ) -> fmt::Result {
1046 FunctionArgSlice::new(&self.0[..]).demangle(ctx, scope)
1047 }
1048 }
1049
1050 impl<'subs, W> DemangleAsInner<'subs, W> for FunctionArgList where W: 'subs + DemangleWrite {}
1051
1052 impl<'subs, W> Demangle<'subs, W> for FunctionArgListAndReturnType
1053 where
1054 W: 'subs + DemangleWrite,
1055 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1056 fn demangle<'prev, 'ctx>(
1057 &'subs self,
1058 ctx: &'ctx mut DemangleContext<'subs, W>,
1059 scope: Option<ArgScopeStack<'prev, 'subs>>,
1060 ) -> fmt::Result {
1061 FunctionArgSlice::new(&self.0[1..]).demangle(ctx, scope)
1062 }
1063 }
1064
1065 impl<'subs, W> DemangleAsInner<'subs, W> for FunctionArgListAndReturnType where
1066 W: 'subs + DemangleWrite
1067 {
1068 }
1069
1070 /// Define a handle to a AST type that lives inside the substitution table. A
1071 /// handle is always either an index into the substitution table, or it is a
1072 /// reference to a "well-known" component.
1073 ///
1074 /// This declares:
1075 ///
1076 /// - The enum of either a back reference into the substitution table or a
1077 /// reference to a "well-known" component
1078 /// - a `Demangle` impl that proxies to the appropriate `Substitutable` in the
1079 /// `SubstitutionTable`
1080 macro_rules! define_handle {
1081 (
1082 $(#[$attr:meta])*
1083 pub enum $typename:ident
1084 ) => {
1085 define_handle! {
1086 $(#[$attr])*
1087 pub enum $typename {}
1088 }
1089 };
1090
1091 (
1092 $(#[$attr:meta])*
1093 pub enum $typename:ident {
1094 $(
1095 $( #[$extra_attr:meta] )*
1096 extra $extra_variant:ident ( $extra_variant_ty:ty ),
1097 )*
1098 }
1099 ) => {
1100 $(#[$attr])*
1101 #[derive(Clone, Debug, PartialEq, Eq)]
1102 pub enum $typename {
1103 /// A reference to a "well-known" component.
1104 WellKnown(WellKnownComponent),
1105
1106 /// A back-reference into the substitution table to a component we
1107 /// have already parsed.
1108 BackReference(usize),
1109
1110 $(
1111 $( #[$extra_attr] )*
1112 $extra_variant( $extra_variant_ty ),
1113 )*
1114 }
1115
1116 impl $typename {
1117 /// If this is a `BackReference`, get its index.
1118 pub fn back_reference(&self) -> Option<usize> {
1119 match *self {
1120 $typename::BackReference(n) => Some(n),
1121 _ => None,
1122 }
1123 }
1124 }
1125
1126 impl<'subs, W> Demangle<'subs, W> for $typename
1127 where
1128 W: 'subs + DemangleWrite
1129 {
1130 #[inline]
1131 fn demangle<'prev, 'ctx>(&'subs self,
1132 ctx: &'ctx mut DemangleContext<'subs, W>,
1133 scope: Option<ArgScopeStack<'prev, 'subs>>)
1134 -> fmt::Result {
1135 match *self {
1136 $typename::WellKnown(ref comp) => comp.demangle(ctx, scope),
1137 $typename::BackReference(idx) => ctx.subs[idx].demangle(ctx, scope),
1138 $(
1139 $typename::$extra_variant(ref extra) => extra.demangle(ctx, scope),
1140 )*
1141 }
1142 }
1143 }
1144
1145 impl<'a> GetLeafName<'a> for $typename {
1146 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1147 match *self {
1148 $typename::WellKnown(ref wk) => wk.get_leaf_name(subs),
1149 $typename::BackReference(idx) => {
1150 subs.get(idx).and_then(|s| s.get_leaf_name(subs))
1151 }
1152 $(
1153 $typename::$extra_variant(ref e) => e.get_leaf_name(subs),
1154 )*
1155 }
1156 }
1157 }
1158 };
1159 }
1160
1161 /// A handle to a component that is usually substitutable, and lives in the
1162 /// substitutions table, but in this particular case does not qualify for
1163 /// substitutions.
1164 #[derive(Clone, Debug, PartialEq, Eq)]
1165 pub struct NonSubstitution(usize);
1166
1167 impl<'subs, W> Demangle<'subs, W> for NonSubstitution
1168 where
1169 W: 'subs + DemangleWrite,
1170 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1171 fn demangle<'prev, 'ctx>(
1172 &'subs self,
1173 ctx: &'ctx mut DemangleContext<'subs, W>,
1174 scope: Option<ArgScopeStack<'prev, 'subs>>,
1175 ) -> fmt::Result {
1176 ctx.subs.non_substitution(self.0).demangle(ctx, scope)
1177 }
1178 }
1179
1180 impl<'a> GetLeafName<'a> for NonSubstitution {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>1181 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1182 subs.get_non_substitution(self.0)
1183 .and_then(|ns| ns.get_leaf_name(subs))
1184 }
1185 }
1186
1187 /// Define a "vocabulary" nonterminal, something like `OperatorName` or
1188 /// `CtorDtorName` that's basically a big list of constant strings.
1189 ///
1190 /// This declares:
1191 ///
1192 /// - the enum itself
1193 /// - a `Parse` impl
1194 /// - a `Demangle` impl
1195 ///
1196 /// See the definition of `CTorDtorName` for an example of its use.
1197 ///
1198 /// Optionally, a piece of user data can be attached to the definitions
1199 /// and be returned by a generated accessor. See `SimpleOperatorName` for
1200 /// an example.
1201 macro_rules! define_vocabulary {
1202 ( $(#[$attr:meta])* pub enum $typename:ident {
1203 $($variant:ident ( $mangled:expr, $printable:expr )),*
1204 } ) => {
1205
1206 $(#[$attr])*
1207 pub enum $typename {
1208 $(
1209 #[doc=$printable]
1210 $variant
1211 ),*
1212 }
1213
1214 impl Parse for $typename {
1215 fn parse<'a, 'b>(ctx: &'a ParseContext,
1216 _subs: &'a mut SubstitutionTable,
1217 input: IndexStr<'b>)
1218 -> Result<($typename, IndexStr<'b>)> {
1219 try_begin_parse!(stringify!($typename), ctx, input);
1220
1221 let mut found_prefix = false;
1222 $(
1223 if let Some((head, tail)) = input.try_split_at($mangled.len()) {
1224 if head.as_ref() == $mangled {
1225 return Ok(($typename::$variant, tail));
1226 }
1227 } else {
1228 found_prefix |= 0 < input.len() &&
1229 input.len() < $mangled.len() &&
1230 input.as_ref() == &$mangled[..input.len()];
1231 }
1232 )*
1233
1234 if input.is_empty() || found_prefix {
1235 Err(error::Error::UnexpectedEnd)
1236 } else {
1237 Err(error::Error::UnexpectedText)
1238 }
1239 }
1240 }
1241
1242 impl<'subs, W> Demangle<'subs, W> for $typename
1243 where
1244 W: 'subs + DemangleWrite,
1245 {
1246 fn demangle<'prev, 'ctx>(
1247 &'subs self,
1248 ctx: &'ctx mut DemangleContext<'subs, W>,
1249 scope: Option<ArgScopeStack<'prev, 'subs>>
1250 ) -> fmt::Result {
1251 let ctx = try_begin_demangle!(self, ctx, scope);
1252
1253 write!(ctx, "{}", match *self {
1254 $(
1255 $typename::$variant => $printable
1256 ),*
1257 })
1258 }
1259 }
1260
1261 impl $typename {
1262 #[allow(dead_code)]
1263 #[inline]
1264 fn starts_with(byte: u8) -> bool {
1265 $(
1266 if $mangled[0] == byte {
1267 return true;
1268 }
1269 )*
1270
1271 false
1272 }
1273 }
1274 };
1275 ( $(#[$attr:meta])* pub enum $typename:ident {
1276 $($variant:ident ( $mangled:expr, $printable:expr, $userdata:expr)),*
1277 }
1278
1279 impl $typename2:ident {
1280 fn $fn_name:ident(&self) -> $userdata_ty:ty;
1281 } ) => {
1282 define_vocabulary! {
1283 $(#[$attr])*
1284 pub enum $typename {
1285 $(
1286 $variant ( $mangled, $printable )
1287 ),*
1288 }
1289 }
1290
1291 impl $typename2 {
1292 fn $fn_name(&self) -> $userdata_ty {
1293 match *self {
1294 $(
1295 $typename2::$variant => $userdata,
1296 )*
1297 }
1298 }
1299 }
1300 };
1301 }
1302
1303 /// The root AST node, and starting production.
1304 ///
1305 /// ```text
1306 /// <mangled-name> ::= _Z <encoding> [<clone-suffix>]*
1307 /// ::= ___Z <encoding> <block_invoke>
1308 /// ::= <type>
1309 ///
1310 /// <block_invoke> ::= _block_invoke
1311 /// ::= _block_invoke<decimal-digit>+
1312 /// ::= _block_invoke_<decimal-digit>+
1313 /// ```
1314 #[derive(Clone, Debug, PartialEq, Eq)]
1315 pub enum MangledName {
1316 /// The encoding of the mangled symbol name.
1317 Encoding(Encoding, Vec<CloneSuffix>),
1318
1319 /// The encoding of the mangled symbol name.
1320 BlockInvoke(Encoding, Option<isize>),
1321
1322 /// A top-level type. Technically not allowed by the standard, however in
1323 /// practice this can happen, and is tested for by libiberty.
1324 Type(TypeHandle),
1325
1326 /// A global constructor or destructor. This is another de facto standard
1327 /// extension (I think originally from `g++`?) that is not actually part of
1328 /// the standard proper.
1329 GlobalCtorDtor(GlobalCtorDtor),
1330 }
1331
1332 impl Parse for MangledName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(MangledName, IndexStr<'b>)>1333 fn parse<'a, 'b>(
1334 ctx: &'a ParseContext,
1335 subs: &'a mut SubstitutionTable,
1336 input: IndexStr<'b>,
1337 ) -> Result<(MangledName, IndexStr<'b>)> {
1338 try_begin_parse!("MangledName", ctx, input);
1339
1340 if let Ok(tail) = consume(b"_Z", input).or_else(|_| consume(b"__Z", input)) {
1341 let (encoding, tail) = Encoding::parse(ctx, subs, tail)?;
1342 let (clone_suffixes, tail) = zero_or_more(ctx, subs, tail)?;
1343 return Ok((MangledName::Encoding(encoding, clone_suffixes), tail));
1344 }
1345
1346 if let Ok(tail) = consume(b"___Z", input).or_else(|_| consume(b"____Z", input)) {
1347 let (encoding, tail) = Encoding::parse(ctx, subs, tail)?;
1348 let tail = consume(b"_block_invoke", tail)?;
1349
1350 let tail_opt = match consume(b"_", tail).or_else(|_| consume(b".", tail)) {
1351 Ok(tail) => Some(parse_number(10, false, tail)?),
1352 Err(_) => parse_number(10, false, tail).ok(),
1353 };
1354
1355 let (digits, tail) = match tail_opt {
1356 Some((digits, tail)) => (Some(digits), tail),
1357 None => (None, tail),
1358 };
1359
1360 return Ok((MangledName::BlockInvoke(encoding, digits), tail));
1361 }
1362
1363 if let Ok(tail) = consume(b"_GLOBAL_", input) {
1364 let (global_ctor_dtor, tail) = GlobalCtorDtor::parse(ctx, subs, tail)?;
1365 return Ok((MangledName::GlobalCtorDtor(global_ctor_dtor), tail));
1366 }
1367
1368 // The libiberty tests also specify that a type can be top level,
1369 // and they are not prefixed with "_Z".
1370 let (ty, tail) = TypeHandle::parse(ctx, subs, input)?;
1371 Ok((MangledName::Type(ty), tail))
1372 }
1373 }
1374
1375 impl<'subs, W> Demangle<'subs, W> for MangledName
1376 where
1377 W: 'subs + DemangleWrite,
1378 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1379 fn demangle<'prev, 'ctx>(
1380 &'subs self,
1381 ctx: &'ctx mut DemangleContext<'subs, W>,
1382 scope: Option<ArgScopeStack<'prev, 'subs>>,
1383 ) -> fmt::Result {
1384 let ctx = try_begin_demangle!(self, ctx, scope);
1385
1386 match *self {
1387 MangledName::Encoding(ref enc, ref cs) => {
1388 enc.demangle(ctx, scope)?;
1389 if !cs.is_empty() && ctx.show_params {
1390 for clone_suffix in cs {
1391 clone_suffix.demangle(ctx, scope)?;
1392 }
1393 }
1394 Ok(())
1395 }
1396 MangledName::BlockInvoke(ref enc, _) => {
1397 write!(ctx, "invocation function for block in ")?;
1398 enc.demangle(ctx, scope)?;
1399 Ok(())
1400 }
1401 MangledName::Type(ref ty) => ty.demangle(ctx, scope),
1402 MangledName::GlobalCtorDtor(ref gcd) => gcd.demangle(ctx, scope),
1403 }
1404 }
1405 }
1406
1407 /// The `<encoding>` production.
1408 ///
1409 /// ```text
1410 /// <encoding> ::= <function name> <bare-function-type>
1411 /// ::= <data name>
1412 /// ::= <special-name>
1413 /// ```
1414 #[derive(Clone, Debug, PartialEq, Eq)]
1415 pub enum Encoding {
1416 /// An encoded function.
1417 Function(Name, BareFunctionType),
1418
1419 /// An encoded static variable.
1420 Data(Name),
1421
1422 /// A special encoding.
1423 Special(SpecialName),
1424 }
1425
1426 impl Parse for Encoding {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Encoding, IndexStr<'b>)>1427 fn parse<'a, 'b>(
1428 ctx: &'a ParseContext,
1429 subs: &'a mut SubstitutionTable,
1430 input: IndexStr<'b>,
1431 ) -> Result<(Encoding, IndexStr<'b>)> {
1432 try_begin_parse!("Encoding", ctx, input);
1433
1434 if let Ok((name, tail)) = Name::parse(ctx, subs, input) {
1435 if let Ok((ty, tail)) = BareFunctionType::parse(ctx, subs, tail) {
1436 return Ok((Encoding::Function(name, ty), tail));
1437 } else {
1438 return Ok((Encoding::Data(name), tail));
1439 }
1440 }
1441
1442 let (name, tail) = SpecialName::parse(ctx, subs, input)?;
1443 Ok((Encoding::Special(name), tail))
1444 }
1445 }
1446
1447 impl<'subs, W> Demangle<'subs, W> for Encoding
1448 where
1449 W: 'subs + DemangleWrite,
1450 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1451 fn demangle<'prev, 'ctx>(
1452 &'subs self,
1453 ctx: &'ctx mut DemangleContext<'subs, W>,
1454 scope: Option<ArgScopeStack<'prev, 'subs>>,
1455 ) -> fmt::Result {
1456 let ctx = try_begin_demangle!(self, ctx, scope);
1457 inner_barrier!(ctx);
1458
1459 match *self {
1460 Encoding::Function(ref name, ref fun_ty) => {
1461 // Even if this function takes no args and doesn't have a return
1462 // value (see below), it will have the void parameter.
1463 debug_assert!(!fun_ty.0.is_empty());
1464
1465 let scope = if let Some(leaf) = name.get_leaf_name(ctx.subs) {
1466 match leaf {
1467 LeafName::SourceName(leaf) => scope.push(leaf),
1468 LeafName::WellKnownComponent(leaf) => scope.push(leaf),
1469 LeafName::Closure(leaf) => scope.push(leaf),
1470 LeafName::UnnamedType(leaf) => scope.push(leaf),
1471 }
1472 } else {
1473 scope
1474 };
1475
1476 // Whether the first type in the BareFunctionType is a return
1477 // type or parameter depends on the context in which it
1478 // appears.
1479 //
1480 // * Templates and functions in a type or parameter position
1481 // have return types, unless they are constructors, destructors,
1482 // or conversion operator functions.
1483 //
1484 // * Non-template functions that are not in a type or parameter
1485 // position do not have a return type.
1486 //
1487 // We know we are not printing a type, so we only need to check
1488 // whether this is a template.
1489 //
1490 // For the details, see
1491 // http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.function-type
1492 let scope = if let Some(template_args) = name.get_template_args(ctx.subs) {
1493 let scope = scope.push(template_args);
1494 if ctx.show_return_type && !name.is_ctor_dtor_conversion(ctx.subs) {
1495 fun_ty.0[0].demangle(ctx, scope)?;
1496 write!(ctx, " ")?;
1497 }
1498
1499 scope
1500 } else {
1501 scope
1502 };
1503
1504 if ctx.show_params {
1505 ctx.push_inner(self);
1506 name.demangle(ctx, scope)?;
1507 if ctx.pop_inner_if(self) {
1508 self.demangle_as_inner(ctx, scope)?;
1509 }
1510 } else {
1511 name.demangle(ctx, scope)?;
1512 }
1513
1514 Ok(())
1515 }
1516 Encoding::Data(ref name) => name.demangle(ctx, scope),
1517 Encoding::Special(ref name) => name.demangle(ctx, scope),
1518 }
1519 }
1520 }
1521
1522 impl<'subs, W> DemangleAsInner<'subs, W> for Encoding
1523 where
1524 W: 'subs + DemangleWrite,
1525 {
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1526 fn demangle_as_inner<'prev, 'ctx>(
1527 &'subs self,
1528 ctx: &'ctx mut DemangleContext<'subs, W>,
1529 scope: Option<ArgScopeStack<'prev, 'subs>>,
1530 ) -> fmt::Result {
1531 if let Encoding::Function(ref name, ref fun_ty) = *self {
1532 let (scope, function_args) =
1533 if let Some(template_args) = name.get_template_args(ctx.subs) {
1534 let scope = scope.push(template_args);
1535 let function_args = FunctionArgListAndReturnType::new(&fun_ty.0);
1536 (scope, function_args as &dyn DemangleAsInner<W>)
1537 } else {
1538 let function_args = FunctionArgList::new(&fun_ty.0);
1539 (scope, function_args as &dyn DemangleAsInner<W>)
1540 };
1541 function_args.demangle_as_inner(ctx, scope)
1542 } else {
1543 unreachable!("we only push Encoding::Function onto the inner stack");
1544 }
1545 }
1546 }
1547
1548 /// <clone-suffix> ::= [ . <clone-type-identifier> ] [ . <nonnegative number> ]*
1549
1550 #[derive(Clone, Debug, PartialEq, Eq)]
1551 pub struct CloneSuffix(CloneTypeIdentifier, Vec<isize>);
1552
1553 impl Parse for CloneSuffix {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(CloneSuffix, IndexStr<'b>)>1554 fn parse<'a, 'b>(
1555 ctx: &'a ParseContext,
1556 subs: &'a mut SubstitutionTable,
1557 input: IndexStr<'b>,
1558 ) -> Result<(CloneSuffix, IndexStr<'b>)> {
1559 try_begin_parse!("CloneSuffix", ctx, input);
1560
1561 let tail = consume(b".", input)?;
1562 let (identifier, mut tail) = CloneTypeIdentifier::parse(ctx, subs, tail)?;
1563
1564 let mut numbers = Vec::with_capacity(1);
1565 while let Ok((n, t)) = consume(b".", tail).and_then(|t| parse_number(10, false, t)) {
1566 numbers.push(n);
1567 tail = t;
1568 }
1569
1570 let clone_suffix = CloneSuffix(identifier, numbers);
1571 Ok((clone_suffix, tail))
1572 }
1573 }
1574
1575 impl<'subs, W> Demangle<'subs, W> for CloneSuffix
1576 where
1577 W: 'subs + DemangleWrite,
1578 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1579 fn demangle<'prev, 'ctx>(
1580 &'subs self,
1581 ctx: &'ctx mut DemangleContext<'subs, W>,
1582 scope: Option<ArgScopeStack<'prev, 'subs>>,
1583 ) -> fmt::Result {
1584 let ctx = try_begin_demangle!(self, ctx, scope);
1585 write!(ctx, " [clone")?;
1586 self.0.demangle(ctx, scope)?;
1587 for nonnegative in &self.1 {
1588 write!(ctx, ".{}", nonnegative)?;
1589 }
1590 write!(ctx, "]")?;
1591 Ok(())
1592 }
1593 }
1594
1595 /// A global constructor or destructor.
1596 #[derive(Clone, Debug, PartialEq, Eq)]
1597 pub enum GlobalCtorDtor {
1598 /// A global constructor.
1599 Ctor(Box<MangledName>),
1600 /// A global destructor.
1601 Dtor(Box<MangledName>),
1602 }
1603
1604 impl Parse for GlobalCtorDtor {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(GlobalCtorDtor, IndexStr<'b>)>1605 fn parse<'a, 'b>(
1606 ctx: &'a ParseContext,
1607 subs: &'a mut SubstitutionTable,
1608 input: IndexStr<'b>,
1609 ) -> Result<(GlobalCtorDtor, IndexStr<'b>)> {
1610 try_begin_parse!("GlobalCtorDtor", ctx, input);
1611
1612 let tail = match input.next_or(error::Error::UnexpectedEnd)? {
1613 (b'_', t) | (b'.', t) | (b'$', t) => t,
1614 _ => return Err(error::Error::UnexpectedText),
1615 };
1616
1617 match tail.next_or(error::Error::UnexpectedEnd)? {
1618 (b'I', tail) => {
1619 let tail = consume(b"_", tail)?;
1620 let (name, tail) = MangledName::parse(ctx, subs, tail)?;
1621 Ok((GlobalCtorDtor::Ctor(Box::new(name)), tail))
1622 }
1623 (b'D', tail) => {
1624 let tail = consume(b"_", tail)?;
1625 let (name, tail) = MangledName::parse(ctx, subs, tail)?;
1626 Ok((GlobalCtorDtor::Dtor(Box::new(name)), tail))
1627 }
1628 _ => Err(error::Error::UnexpectedText),
1629 }
1630 }
1631 }
1632
1633 impl<'subs, W> Demangle<'subs, W> for GlobalCtorDtor
1634 where
1635 W: 'subs + DemangleWrite,
1636 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1637 fn demangle<'prev, 'ctx>(
1638 &'subs self,
1639 ctx: &'ctx mut DemangleContext<'subs, W>,
1640 scope: Option<ArgScopeStack<'prev, 'subs>>,
1641 ) -> fmt::Result {
1642 let ctx = try_begin_demangle!(self, ctx, scope);
1643 inner_barrier!(ctx);
1644
1645 let saved_show_params = ctx.show_params;
1646 ctx.show_params = true;
1647 let ret = match *self {
1648 GlobalCtorDtor::Ctor(ref name) => {
1649 write!(ctx, "global constructors keyed to ")?;
1650 name.demangle(ctx, scope)
1651 }
1652 GlobalCtorDtor::Dtor(ref name) => {
1653 write!(ctx, "global destructors keyed to ")?;
1654 name.demangle(ctx, scope)
1655 }
1656 };
1657 ctx.show_params = saved_show_params;
1658 ret
1659 }
1660 }
1661
1662 /// The `<name>` production.
1663 ///
1664 /// ```text
1665 /// <name> ::= <nested-name>
1666 /// ::= <unscoped-name>
1667 /// ::= <unscoped-template-name> <template-args>
1668 /// ::= <local-name>
1669 /// ```
1670 #[derive(Clone, Debug, PartialEq, Eq)]
1671 pub enum Name {
1672 /// A nested name
1673 Nested(NestedName),
1674
1675 /// An unscoped name.
1676 Unscoped(UnscopedName),
1677
1678 /// An unscoped template.
1679 UnscopedTemplate(UnscopedTemplateNameHandle, TemplateArgs),
1680
1681 /// A local name.
1682 Local(LocalName),
1683 }
1684
1685 impl Parse for Name {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Name, IndexStr<'b>)>1686 fn parse<'a, 'b>(
1687 ctx: &'a ParseContext,
1688 subs: &'a mut SubstitutionTable,
1689 input: IndexStr<'b>,
1690 ) -> Result<(Name, IndexStr<'b>)> {
1691 try_begin_parse!("Name", ctx, input);
1692
1693 if let Ok((name, tail)) = NestedName::parse(ctx, subs, input) {
1694 return Ok((Name::Nested(name), tail));
1695 }
1696
1697 if let Ok((name, tail)) = UnscopedName::parse(ctx, subs, input) {
1698 if tail.peek() == Some(b'I') {
1699 let name = UnscopedTemplateName(name);
1700 let idx = subs.insert(Substitutable::UnscopedTemplateName(name));
1701 let handle = UnscopedTemplateNameHandle::BackReference(idx);
1702
1703 let (args, tail) = TemplateArgs::parse(ctx, subs, tail)?;
1704 return Ok((Name::UnscopedTemplate(handle, args), tail));
1705 } else {
1706 return Ok((Name::Unscoped(name), tail));
1707 }
1708 }
1709
1710 if let Ok((name, tail)) = UnscopedTemplateNameHandle::parse(ctx, subs, input) {
1711 let (args, tail) = TemplateArgs::parse(ctx, subs, tail)?;
1712 return Ok((Name::UnscopedTemplate(name, args), tail));
1713 }
1714
1715 let (name, tail) = LocalName::parse(ctx, subs, input)?;
1716 Ok((Name::Local(name), tail))
1717 }
1718 }
1719
1720 impl<'subs, W> Demangle<'subs, W> for Name
1721 where
1722 W: 'subs + DemangleWrite,
1723 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1724 fn demangle<'prev, 'ctx>(
1725 &'subs self,
1726 ctx: &'ctx mut DemangleContext<'subs, W>,
1727 scope: Option<ArgScopeStack<'prev, 'subs>>,
1728 ) -> fmt::Result {
1729 let ctx = try_begin_demangle!(self, ctx, scope);
1730
1731 match *self {
1732 Name::Nested(ref nested) => nested.demangle(ctx, scope),
1733 Name::Unscoped(ref unscoped) => unscoped.demangle(ctx, scope),
1734 Name::UnscopedTemplate(ref template, ref args) => {
1735 template.demangle(ctx, scope.push(args))?;
1736 args.demangle(ctx, scope)
1737 }
1738 Name::Local(ref local) => local.demangle(ctx, scope),
1739 }
1740 }
1741 }
1742
1743 impl GetTemplateArgs for Name {
get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>1744 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
1745 match *self {
1746 Name::UnscopedTemplate(_, ref args) => Some(args),
1747 Name::Nested(ref nested) => nested.get_template_args(subs),
1748 Name::Local(ref local) => local.get_template_args(subs),
1749 Name::Unscoped(_) => None,
1750 }
1751 }
1752 }
1753
1754 impl<'a> GetLeafName<'a> for Name {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>1755 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1756 match *self {
1757 Name::UnscopedTemplate(ref templ, _) => templ.get_leaf_name(subs),
1758 Name::Nested(ref nested) => nested.get_leaf_name(subs),
1759 Name::Unscoped(ref unscoped) => unscoped.get_leaf_name(subs),
1760 Name::Local(ref local) => local.get_leaf_name(subs),
1761 }
1762 }
1763 }
1764
1765 impl IsCtorDtorConversion for Name {
is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool1766 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
1767 match *self {
1768 Name::Unscoped(ref unscoped) => unscoped.is_ctor_dtor_conversion(subs),
1769 Name::Nested(ref nested) => nested.is_ctor_dtor_conversion(subs),
1770 Name::Local(_) | Name::UnscopedTemplate(..) => false,
1771 }
1772 }
1773 }
1774
1775 /// The `<unscoped-name>` production.
1776 ///
1777 /// ```text
1778 /// <unscoped-name> ::= <unqualified-name>
1779 /// ::= St <unqualified-name> # ::std::
1780 /// ```
1781 #[derive(Clone, Debug, PartialEq, Eq)]
1782 pub enum UnscopedName {
1783 /// An unqualified name.
1784 Unqualified(UnqualifiedName),
1785
1786 /// A name within the `std::` namespace.
1787 Std(UnqualifiedName),
1788 }
1789
1790 impl Parse for UnscopedName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(UnscopedName, IndexStr<'b>)>1791 fn parse<'a, 'b>(
1792 ctx: &'a ParseContext,
1793 subs: &'a mut SubstitutionTable,
1794 input: IndexStr<'b>,
1795 ) -> Result<(UnscopedName, IndexStr<'b>)> {
1796 try_begin_parse!("UnscopedName", ctx, input);
1797
1798 if let Ok(tail) = consume(b"St", input) {
1799 let (name, tail) = UnqualifiedName::parse(ctx, subs, tail)?;
1800 return Ok((UnscopedName::Std(name), tail));
1801 }
1802
1803 let (name, tail) = UnqualifiedName::parse(ctx, subs, input)?;
1804 Ok((UnscopedName::Unqualified(name), tail))
1805 }
1806 }
1807
1808 impl<'subs, W> Demangle<'subs, W> for UnscopedName
1809 where
1810 W: 'subs + DemangleWrite,
1811 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1812 fn demangle<'prev, 'ctx>(
1813 &'subs self,
1814 ctx: &'ctx mut DemangleContext<'subs, W>,
1815 scope: Option<ArgScopeStack<'prev, 'subs>>,
1816 ) -> fmt::Result {
1817 let ctx = try_begin_demangle!(self, ctx, scope);
1818
1819 match *self {
1820 UnscopedName::Unqualified(ref unqualified) => unqualified.demangle(ctx, scope),
1821 UnscopedName::Std(ref std) => {
1822 write!(ctx, "std::")?;
1823 std.demangle(ctx, scope)
1824 }
1825 }
1826 }
1827 }
1828
1829 impl<'a> GetLeafName<'a> for UnscopedName {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>1830 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1831 match *self {
1832 UnscopedName::Unqualified(ref name) | UnscopedName::Std(ref name) => {
1833 name.get_leaf_name(subs)
1834 }
1835 }
1836 }
1837 }
1838
1839 impl IsCtorDtorConversion for UnscopedName {
is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool1840 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
1841 match *self {
1842 UnscopedName::Unqualified(ref name) | UnscopedName::Std(ref name) => {
1843 name.is_ctor_dtor_conversion(subs)
1844 }
1845 }
1846 }
1847 }
1848
1849 /// The `<unscoped-template-name>` production.
1850 ///
1851 /// ```text
1852 /// <unscoped-template-name> ::= <unscoped-name>
1853 /// ::= <substitution>
1854 /// ```
1855 #[derive(Clone, Debug, PartialEq, Eq)]
1856 pub struct UnscopedTemplateName(UnscopedName);
1857
1858 define_handle! {
1859 /// A handle to an `UnscopedTemplateName`.
1860 pub enum UnscopedTemplateNameHandle {
1861 /// A handle to some `<unscoped-name>` component that isn't by itself
1862 /// substitutable.
1863 extra NonSubstitution(NonSubstitution),
1864 }
1865 }
1866
1867 impl Parse for UnscopedTemplateNameHandle {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(UnscopedTemplateNameHandle, IndexStr<'b>)>1868 fn parse<'a, 'b>(
1869 ctx: &'a ParseContext,
1870 subs: &'a mut SubstitutionTable,
1871 input: IndexStr<'b>,
1872 ) -> Result<(UnscopedTemplateNameHandle, IndexStr<'b>)> {
1873 try_begin_parse!("UnscopedTemplateNameHandle", ctx, input);
1874
1875 if let Ok((name, tail)) = UnscopedName::parse(ctx, subs, input) {
1876 let name = UnscopedTemplateName(name);
1877 let idx = subs.insert(Substitutable::UnscopedTemplateName(name));
1878 let handle = UnscopedTemplateNameHandle::BackReference(idx);
1879 return Ok((handle, tail));
1880 }
1881
1882 let (sub, tail) = Substitution::parse(ctx, subs, input)?;
1883
1884 match sub {
1885 Substitution::WellKnown(component) => {
1886 Ok((UnscopedTemplateNameHandle::WellKnown(component), tail))
1887 }
1888 Substitution::BackReference(idx) => {
1889 // TODO: should this check/assert that subs[idx] is an
1890 // UnscopedTemplateName?
1891 Ok((UnscopedTemplateNameHandle::BackReference(idx), tail))
1892 }
1893 }
1894 }
1895 }
1896
1897 impl<'subs, W> Demangle<'subs, W> for UnscopedTemplateName
1898 where
1899 W: 'subs + DemangleWrite,
1900 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result1901 fn demangle<'prev, 'ctx>(
1902 &'subs self,
1903 ctx: &'ctx mut DemangleContext<'subs, W>,
1904 scope: Option<ArgScopeStack<'prev, 'subs>>,
1905 ) -> fmt::Result {
1906 let ctx = try_begin_demangle!(self, ctx, scope);
1907
1908 self.0.demangle(ctx, scope)
1909 }
1910 }
1911
1912 impl<'a> GetLeafName<'a> for UnscopedTemplateName {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>1913 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1914 self.0.get_leaf_name(subs)
1915 }
1916 }
1917
1918 /// The `<nested-name>` production.
1919 ///
1920 /// ```text
1921 /// <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
1922 /// ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
1923 /// ```
1924 #[derive(Clone, Debug, PartialEq, Eq)]
1925 pub enum NestedName {
1926 /// A nested name.
1927 Unqualified(
1928 CvQualifiers,
1929 Option<RefQualifier>,
1930 PrefixHandle,
1931 UnqualifiedName,
1932 ),
1933
1934 /// A nested template name. The `<template-args>` are part of the `PrefixHandle`.
1935 Template(CvQualifiers, Option<RefQualifier>, PrefixHandle),
1936 }
1937
1938 impl Parse for NestedName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(NestedName, IndexStr<'b>)>1939 fn parse<'a, 'b>(
1940 ctx: &'a ParseContext,
1941 subs: &'a mut SubstitutionTable,
1942 input: IndexStr<'b>,
1943 ) -> Result<(NestedName, IndexStr<'b>)> {
1944 try_begin_parse!("NestedName", ctx, input);
1945
1946 let tail = consume(b"N", input)?;
1947
1948 let (cv_qualifiers, tail) = if let Ok((q, tail)) = CvQualifiers::parse(ctx, subs, tail) {
1949 (q, tail)
1950 } else {
1951 (Default::default(), tail)
1952 };
1953
1954 let (ref_qualifier, tail) = if let Ok((r, tail)) = RefQualifier::parse(ctx, subs, tail) {
1955 (Some(r), tail)
1956 } else {
1957 (None, tail)
1958 };
1959
1960 let (prefix, tail) = PrefixHandle::parse(ctx, subs, tail)?;
1961 let tail = consume(b"E", tail)?;
1962
1963 let substitutable = match prefix {
1964 PrefixHandle::BackReference(idx) => subs.get(idx),
1965 PrefixHandle::NonSubstitution(NonSubstitution(idx)) => subs.get_non_substitution(idx),
1966 PrefixHandle::WellKnown(_) => None,
1967 };
1968
1969 match substitutable {
1970 Some(&Substitutable::Prefix(Prefix::Nested(ref prefix, ref name))) => Ok((
1971 NestedName::Unqualified(cv_qualifiers, ref_qualifier, prefix.clone(), name.clone()),
1972 tail,
1973 )),
1974 Some(&Substitutable::Prefix(Prefix::Template(..))) => Ok((
1975 NestedName::Template(cv_qualifiers, ref_qualifier, prefix),
1976 tail,
1977 )),
1978 _ => Err(error::Error::UnexpectedText),
1979 }
1980 }
1981 }
1982
1983 impl NestedName {
1984 /// Get the CV-qualifiers for this name.
cv_qualifiers(&self) -> &CvQualifiers1985 pub fn cv_qualifiers(&self) -> &CvQualifiers {
1986 match *self {
1987 NestedName::Unqualified(ref q, ..) | NestedName::Template(ref q, ..) => q,
1988 }
1989 }
1990
1991 /// Get the ref-qualifier for this name, if one exists.
ref_qualifier(&self) -> Option<&RefQualifier>1992 pub fn ref_qualifier(&self) -> Option<&RefQualifier> {
1993 match *self {
1994 NestedName::Unqualified(_, Some(ref r), ..)
1995 | NestedName::Template(_, Some(ref r), ..) => Some(r),
1996 _ => None,
1997 }
1998 }
1999
2000 // Not public because the prefix means different things for different
2001 // variants, and for `::Template` it actually contains part of what
2002 // conceptually belongs to `<nested-name>`.
prefix(&self) -> &PrefixHandle2003 fn prefix(&self) -> &PrefixHandle {
2004 match *self {
2005 NestedName::Unqualified(_, _, ref p, _) | NestedName::Template(_, _, ref p) => p,
2006 }
2007 }
2008 }
2009
2010 impl<'subs, W> Demangle<'subs, W> for NestedName
2011 where
2012 W: 'subs + DemangleWrite,
2013 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result2014 fn demangle<'prev, 'ctx>(
2015 &'subs self,
2016 ctx: &'ctx mut DemangleContext<'subs, W>,
2017 scope: Option<ArgScopeStack<'prev, 'subs>>,
2018 ) -> fmt::Result {
2019 let ctx = try_begin_demangle!(self, ctx, scope);
2020
2021 match *self {
2022 NestedName::Unqualified(_, _, ref p, ref name) => {
2023 ctx.push_demangle_node(DemangleNodeType::NestedName);
2024 p.demangle(ctx, scope)?;
2025 if name.accepts_double_colon() {
2026 ctx.write_str("::")?;
2027 }
2028 name.demangle(ctx, scope)?;
2029 ctx.pop_demangle_node();
2030 }
2031 NestedName::Template(_, _, ref p) => {
2032 ctx.is_template_prefix_in_nested_name = true;
2033 p.demangle(ctx, scope)?;
2034 ctx.is_template_prefix_in_nested_name = false;
2035 }
2036 }
2037
2038 if let Some(inner) = ctx.pop_inner() {
2039 inner.demangle_as_inner(ctx, scope)?;
2040 }
2041
2042 if self.cv_qualifiers() != &CvQualifiers::default() && ctx.show_params {
2043 self.cv_qualifiers().demangle(ctx, scope)?;
2044 }
2045
2046 if let Some(ref refs) = self.ref_qualifier() {
2047 ctx.ensure_space()?;
2048 refs.demangle(ctx, scope)?;
2049 }
2050
2051 Ok(())
2052 }
2053 }
2054
2055 impl GetTemplateArgs for NestedName {
get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>2056 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
2057 match *self {
2058 NestedName::Template(_, _, ref prefix) => prefix.get_template_args(subs),
2059 _ => None,
2060 }
2061 }
2062 }
2063
2064 impl<'a> GetLeafName<'a> for NestedName {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>2065 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
2066 match *self {
2067 NestedName::Unqualified(_, _, ref prefix, ref name) => name
2068 .get_leaf_name(subs)
2069 .or_else(|| prefix.get_leaf_name(subs)),
2070 NestedName::Template(_, _, ref prefix) => prefix.get_leaf_name(subs),
2071 }
2072 }
2073 }
2074
2075 impl IsCtorDtorConversion for NestedName {
is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool2076 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
2077 self.prefix().is_ctor_dtor_conversion(subs)
2078 }
2079 }
2080
2081 /// The `<prefix>` production.
2082 ///
2083 /// ```text
2084 /// <prefix> ::= <unqualified-name>
2085 /// ::= <prefix> <unqualified-name>
2086 /// ::= <template-prefix> <template-args>
2087 /// ::= <template-param>
2088 /// ::= <decltype>
2089 /// ::= <prefix> <data-member-prefix>
2090 /// ::= <substitution>
2091 ///
2092 /// <template-prefix> ::= <template unqualified-name>
2093 /// ::= <prefix> <template unqualified-name>
2094 /// ::= <template-param>
2095 /// ::= <substitution>
2096 /// ```
2097 #[derive(Clone, Debug, PartialEq, Eq)]
2098 pub enum Prefix {
2099 /// An unqualified name.
2100 Unqualified(UnqualifiedName),
2101
2102 /// Some nested name.
2103 Nested(PrefixHandle, UnqualifiedName),
2104
2105 /// A prefix and template arguments.
2106 Template(PrefixHandle, TemplateArgs),
2107
2108 /// A template parameter.
2109 TemplateParam(TemplateParam),
2110
2111 /// A decltype.
2112 Decltype(Decltype),
2113
2114 /// A prefix and data member.
2115 DataMember(PrefixHandle, DataMemberPrefix),
2116 }
2117
2118 impl GetTemplateArgs for Prefix {
get_template_args<'a>(&'a self, _: &'a SubstitutionTable) -> Option<&'a TemplateArgs>2119 fn get_template_args<'a>(&'a self, _: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
2120 match *self {
2121 Prefix::Template(_, ref args) => Some(args),
2122 Prefix::Unqualified(_)
2123 | Prefix::Nested(_, _)
2124 | Prefix::TemplateParam(_)
2125 | Prefix::Decltype(_)
2126 | Prefix::DataMember(_, _) => None,
2127 }
2128 }
2129 }
2130
2131 define_handle! {
2132 /// A reference to a parsed `<prefix>` production.
2133 pub enum PrefixHandle {
2134 /// A handle to some `<prefix>` component that isn't by itself
2135 /// substitutable; instead, it's only substitutable *with* its parent
2136 /// component.
2137 extra NonSubstitution(NonSubstitution),
2138 }
2139 }
2140
2141 impl Parse for PrefixHandle {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(PrefixHandle, IndexStr<'b>)>2142 fn parse<'a, 'b>(
2143 ctx: &'a ParseContext,
2144 subs: &'a mut SubstitutionTable,
2145 input: IndexStr<'b>,
2146 ) -> Result<(PrefixHandle, IndexStr<'b>)> {
2147 try_begin_parse!("PrefixHandle", ctx, input);
2148
2149 #[inline]
2150 fn save(
2151 subs: &mut SubstitutionTable,
2152 prefix: Prefix,
2153 tail_tail: IndexStr<'_>,
2154 ) -> PrefixHandle {
2155 if let Some(b'E') = tail_tail.peek() {
2156 // An `E` means that we just finished parsing a `<nested-name>`
2157 // and this final set of prefixes isn't substitutable itself,
2158 // only as part of the whole `<nested-name>`. Since they are
2159 // effectively equivalent, it doesn't make sense to add entries
2160 // for both.
2161 let idx = subs.insert_non_substitution(Substitutable::Prefix(prefix));
2162 PrefixHandle::NonSubstitution(NonSubstitution(idx))
2163 } else {
2164 let idx = subs.insert(Substitutable::Prefix(prefix));
2165 PrefixHandle::BackReference(idx)
2166 }
2167 }
2168
2169 let mut tail = input;
2170 let mut current = None;
2171
2172 loop {
2173 try_begin_parse!("PrefixHandle iteration", ctx, tail);
2174
2175 match tail.peek() {
2176 Some(b'E') | None => {
2177 if let Some(handle) = current {
2178 return Ok((handle, tail));
2179 } else {
2180 return Err(error::Error::UnexpectedEnd);
2181 }
2182 }
2183 Some(b'S') => {
2184 // <prefix> ::= <substitution>
2185 let (sub, tail_tail) = Substitution::parse(ctx, subs, tail)?;
2186 current = Some(match sub {
2187 Substitution::WellKnown(component) => PrefixHandle::WellKnown(component),
2188 Substitution::BackReference(idx) => {
2189 // TODO: do we need to check that the idx actually points to
2190 // a Prefix?
2191 PrefixHandle::BackReference(idx)
2192 }
2193 });
2194 tail = tail_tail;
2195 }
2196 Some(b'T') => {
2197 // <prefix> ::= <template-param>
2198 let (param, tail_tail) = TemplateParam::parse(ctx, subs, tail)?;
2199 current = Some(save(subs, Prefix::TemplateParam(param), tail_tail));
2200 tail = tail_tail;
2201 }
2202 Some(b'D') => {
2203 // Either
2204 //
2205 // <prefix> ::= <decltype>
2206 //
2207 // or
2208 //
2209 // <prefix> ::= <unqualified-name> ::= <ctor-dtor-name>
2210 if let Ok((decltype, tail_tail)) = Decltype::parse(ctx, subs, tail) {
2211 current = Some(save(subs, Prefix::Decltype(decltype), tail_tail));
2212 tail = tail_tail;
2213 } else {
2214 let (name, tail_tail) = UnqualifiedName::parse(ctx, subs, tail)?;
2215 let prefix = match current {
2216 None => Prefix::Unqualified(name),
2217 Some(handle) => Prefix::Nested(handle, name),
2218 };
2219 current = Some(save(subs, prefix, tail_tail));
2220 tail = tail_tail;
2221 }
2222 }
2223 Some(b'I')
2224 if current.is_some() && current.as_ref().unwrap().is_template_prefix() =>
2225 {
2226 // <prefix> ::= <template-prefix> <template-args>
2227 let (args, tail_tail) = TemplateArgs::parse(ctx, subs, tail)?;
2228 let prefix = Prefix::Template(current.unwrap(), args);
2229 current = Some(save(subs, prefix, tail_tail));
2230 tail = tail_tail;
2231 }
2232 Some(c) if current.is_some() && SourceName::starts_with(c) => {
2233 // Either
2234 //
2235 // <prefix> ::= <unqualified-name> ::= <source-name>
2236 //
2237 // or
2238 //
2239 // <prefix> ::= <data-member-prefix> ::= <prefix> <source-name> M
2240 debug_assert!(SourceName::starts_with(c));
2241 debug_assert!(DataMemberPrefix::starts_with(c));
2242
2243 let (name, tail_tail) = SourceName::parse(ctx, subs, tail)?;
2244 if tail_tail.peek() == Some(b'M') {
2245 let prefix = Prefix::DataMember(current.unwrap(), DataMemberPrefix(name));
2246 current = Some(save(subs, prefix, tail_tail));
2247 tail = consume(b"M", tail_tail).unwrap();
2248 } else {
2249 let name = UnqualifiedName::Source(name);
2250 let prefix = match current {
2251 None => Prefix::Unqualified(name),
2252 Some(handle) => Prefix::Nested(handle, name),
2253 };
2254 current = Some(save(subs, prefix, tail_tail));
2255 tail = tail_tail;
2256 }
2257 }
2258 Some(c) if UnqualifiedName::starts_with(c, &tail) => {
2259 // <prefix> ::= <unqualified-name>
2260 let (name, tail_tail) = UnqualifiedName::parse(ctx, subs, tail)?;
2261 let prefix = match current {
2262 None => Prefix::Unqualified(name),
2263 Some(handle) => Prefix::Nested(handle, name),
2264 };
2265 current = Some(save(subs, prefix, tail_tail));
2266 tail = tail_tail;
2267 }
2268 Some(_) => {
2269 if let Some(handle) = current {
2270 return Ok((handle, tail));
2271 } else if tail.is_empty() {
2272 return Err(error::Error::UnexpectedEnd);
2273 } else {
2274 return Err(error::Error::UnexpectedText);
2275 }
2276 }
2277 }
2278 }
2279 }
2280 }
2281
2282 impl<'a> GetLeafName<'a> for Prefix {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>2283 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
2284 match *self {
2285 Prefix::Nested(ref prefix, ref name) => name
2286 .get_leaf_name(subs)
2287 .or_else(|| prefix.get_leaf_name(subs)),
2288 Prefix::Unqualified(ref name) => name.get_leaf_name(subs),
2289 Prefix::Template(ref prefix, _) => prefix.get_leaf_name(subs),
2290 Prefix::DataMember(_, ref name) => name.get_leaf_name(subs),
2291 Prefix::TemplateParam(_) | Prefix::Decltype(_) => None,
2292 }
2293 }
2294 }
2295
2296 impl GetTemplateArgs for PrefixHandle {
2297 // XXX: Not an impl GetTemplateArgs for PrefixHandle because the 'me
2298 // reference to self may not live long enough.
get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>2299 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
2300 match *self {
2301 PrefixHandle::BackReference(idx) => {
2302 if let Some(&Substitutable::Prefix(ref p)) = subs.get(idx) {
2303 p.get_template_args(subs)
2304 } else {
2305 None
2306 }
2307 }
2308 PrefixHandle::NonSubstitution(NonSubstitution(idx)) => {
2309 if let Some(&Substitutable::Prefix(ref p)) = subs.get_non_substitution(idx) {
2310 p.get_template_args(subs)
2311 } else {
2312 None
2313 }
2314 }
2315 _ => None,
2316 }
2317 }
2318 }
2319
2320 impl<'subs, W> Demangle<'subs, W> for Prefix
2321 where
2322 W: 'subs + DemangleWrite,
2323 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result2324 fn demangle<'prev, 'ctx>(
2325 &'subs self,
2326 ctx: &'ctx mut DemangleContext<'subs, W>,
2327 scope: Option<ArgScopeStack<'prev, 'subs>>,
2328 ) -> fmt::Result {
2329 let ctx = try_begin_demangle!(self, ctx, scope);
2330 if ctx.is_template_prefix {
2331 ctx.push_demangle_node(DemangleNodeType::TemplatePrefix);
2332 ctx.is_template_prefix = false;
2333 } else if ctx.is_template_prefix_in_nested_name {
2334 ctx.push_demangle_node(DemangleNodeType::NestedName);
2335 ctx.is_template_prefix_in_nested_name = false;
2336 } else {
2337 ctx.push_demangle_node(DemangleNodeType::Prefix);
2338 }
2339
2340 let ret = match *self {
2341 Prefix::Unqualified(ref unqualified) => unqualified.demangle(ctx, scope),
2342 Prefix::Nested(ref prefix, ref unqualified) => {
2343 prefix.demangle(ctx, scope)?;
2344 if unqualified.accepts_double_colon() {
2345 write!(ctx, "::")?;
2346 }
2347 unqualified.demangle(ctx, scope)
2348 }
2349 Prefix::Template(ref prefix, ref args) => {
2350 ctx.is_template_prefix = true;
2351 prefix.demangle(ctx, scope)?;
2352 ctx.is_template_prefix = false;
2353 args.demangle(ctx, scope)
2354 }
2355 Prefix::TemplateParam(ref param) => param.demangle(ctx, scope),
2356 Prefix::Decltype(ref dt) => dt.demangle(ctx, scope),
2357 Prefix::DataMember(ref prefix, ref member) => {
2358 prefix.demangle(ctx, scope)?;
2359 write!(ctx, "::")?;
2360 member.demangle(ctx, scope)
2361 }
2362 };
2363 ctx.pop_demangle_node();
2364 ret
2365 }
2366 }
2367
2368 impl IsCtorDtorConversion for Prefix {
is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool2369 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
2370 match *self {
2371 Prefix::Unqualified(ref unqualified) | Prefix::Nested(_, ref unqualified) => {
2372 unqualified.is_ctor_dtor_conversion(subs)
2373 }
2374 Prefix::Template(ref prefix, _) => prefix.is_ctor_dtor_conversion(subs),
2375 _ => false,
2376 }
2377 }
2378 }
2379
2380 impl IsCtorDtorConversion for PrefixHandle {
is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool2381 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
2382 match *self {
2383 PrefixHandle::BackReference(idx) => {
2384 if let Some(sub) = subs.get(idx) {
2385 sub.is_ctor_dtor_conversion(subs)
2386 } else {
2387 false
2388 }
2389 }
2390 PrefixHandle::NonSubstitution(NonSubstitution(idx)) => {
2391 if let Some(sub) = subs.get_non_substitution(idx) {
2392 sub.is_ctor_dtor_conversion(subs)
2393 } else {
2394 false
2395 }
2396 }
2397 PrefixHandle::WellKnown(_) => false,
2398 }
2399 }
2400 }
2401
2402 impl PrefixHandle {
2403 // Is this <prefix> also a valid <template-prefix> production? Not to be
2404 // confused with the `GetTemplateArgs` trait.
is_template_prefix(&self) -> bool2405 fn is_template_prefix(&self) -> bool {
2406 match *self {
2407 PrefixHandle::BackReference(_) | PrefixHandle::WellKnown(_) => true,
2408 PrefixHandle::NonSubstitution(_) => false,
2409 }
2410 }
2411 }
2412
2413 /// The `<unqualified-name>` production.
2414 ///
2415 /// ```text
2416 /// <unqualified-name> ::= <operator-name>
2417 /// ::= <ctor-dtor-name>
2418 /// ::= <source-name>
2419 /// ::= <local-source-name>
2420 /// ::= <unnamed-type-name>
2421 /// ::= <abi-tag>
2422 /// ::= <closure-type-name>
2423 ///
2424 /// # I think this is from an older version of the standard. It isn't in the
2425 /// # current version, but all the other demanglers support it, so we will too.
2426 /// <local-source-name> ::= L <source-name> [<discriminator>]
2427 /// ```
2428 #[derive(Clone, Debug, PartialEq, Eq)]
2429 pub enum UnqualifiedName {
2430 /// An operator name.
2431 Operator(OperatorName),
2432 /// A constructor or destructor name.
2433 CtorDtor(CtorDtorName),
2434 /// A source name.
2435 Source(SourceName),
2436 /// A local source name.
2437 LocalSourceName(SourceName, Option<Discriminator>),
2438 /// A generated name for an unnamed type.
2439 UnnamedType(UnnamedTypeName),
2440 /// An ABI tag.
2441 ABITag(TaggedName),
2442 /// A closure type name
2443 ClosureType(ClosureTypeName),
2444 }
2445
2446 impl Parse for UnqualifiedName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(UnqualifiedName, IndexStr<'b>)>2447 fn parse<'a, 'b>(
2448 ctx: &'a ParseContext,
2449 subs: &'a mut SubstitutionTable,
2450 input: IndexStr<'b>,
2451 ) -> Result<(UnqualifiedName, IndexStr<'b>)> {
2452 try_begin_parse!("UnqualifiedName", ctx, input);
2453
2454 if let Ok((op, tail)) = OperatorName::parse(ctx, subs, input) {
2455 return Ok((UnqualifiedName::Operator(op), tail));
2456 }
2457
2458 if let Ok((ctor_dtor, tail)) = CtorDtorName::parse(ctx, subs, input) {
2459 return Ok((UnqualifiedName::CtorDtor(ctor_dtor), tail));
2460 }
2461
2462 if let Ok(tail) = consume(b"L", input) {
2463 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
2464 let (discr, tail) = if let Ok((d, t)) = Discriminator::parse(ctx, subs, tail) {
2465 (Some(d), t)
2466 } else {
2467 (None, tail)
2468 };
2469 return Ok((UnqualifiedName::LocalSourceName(name, discr), tail));
2470 }
2471
2472 if let Ok((source, tail)) = SourceName::parse(ctx, subs, input) {
2473 return Ok((UnqualifiedName::Source(source), tail));
2474 }
2475
2476 if let Ok((tagged, tail)) = TaggedName::parse(ctx, subs, input) {
2477 return Ok((UnqualifiedName::ABITag(tagged), tail));
2478 }
2479
2480 if let Ok((closure, tail)) = ClosureTypeName::parse(ctx, subs, input) {
2481 return Ok((UnqualifiedName::ClosureType(closure), tail));
2482 }
2483
2484 UnnamedTypeName::parse(ctx, subs, input)
2485 .map(|(unnamed, tail)| (UnqualifiedName::UnnamedType(unnamed), tail))
2486 }
2487 }
2488
2489 impl<'subs, W> Demangle<'subs, W> for UnqualifiedName
2490 where
2491 W: 'subs + DemangleWrite,
2492 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result2493 fn demangle<'prev, 'ctx>(
2494 &'subs self,
2495 ctx: &'ctx mut DemangleContext<'subs, W>,
2496 scope: Option<ArgScopeStack<'prev, 'subs>>,
2497 ) -> fmt::Result {
2498 let ctx = try_begin_demangle!(self, ctx, scope);
2499
2500 ctx.push_demangle_node(DemangleNodeType::UnqualifiedName);
2501 let ret = match *self {
2502 UnqualifiedName::Operator(ref op_name) => {
2503 write!(ctx, "operator")?;
2504 op_name.demangle(ctx, scope)
2505 }
2506 UnqualifiedName::CtorDtor(ref ctor_dtor) => ctor_dtor.demangle(ctx, scope),
2507 UnqualifiedName::Source(ref name) | UnqualifiedName::LocalSourceName(ref name, ..) => {
2508 name.demangle(ctx, scope)
2509 }
2510 UnqualifiedName::UnnamedType(ref unnamed) => unnamed.demangle(ctx, scope),
2511 UnqualifiedName::ABITag(ref tagged) => tagged.demangle(ctx, scope),
2512 UnqualifiedName::ClosureType(ref closure) => closure.demangle(ctx, scope),
2513 };
2514 ctx.pop_demangle_node();
2515 ret
2516 }
2517 }
2518
2519 impl<'a> GetLeafName<'a> for UnqualifiedName {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>2520 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
2521 match *self {
2522 UnqualifiedName::ABITag(_)
2523 | UnqualifiedName::Operator(_)
2524 | UnqualifiedName::CtorDtor(_) => None,
2525 UnqualifiedName::UnnamedType(ref name) => Some(LeafName::UnnamedType(name)),
2526 UnqualifiedName::ClosureType(ref closure) => closure.get_leaf_name(subs),
2527 UnqualifiedName::Source(ref name) | UnqualifiedName::LocalSourceName(ref name, _) => {
2528 Some(LeafName::SourceName(name))
2529 }
2530 }
2531 }
2532 }
2533
2534 impl IsCtorDtorConversion for UnqualifiedName {
is_ctor_dtor_conversion(&self, _: &SubstitutionTable) -> bool2535 fn is_ctor_dtor_conversion(&self, _: &SubstitutionTable) -> bool {
2536 match *self {
2537 UnqualifiedName::CtorDtor(_)
2538 | UnqualifiedName::Operator(OperatorName::Conversion(_)) => true,
2539 UnqualifiedName::Operator(_)
2540 | UnqualifiedName::Source(_)
2541 | UnqualifiedName::LocalSourceName(..)
2542 | UnqualifiedName::UnnamedType(_)
2543 | UnqualifiedName::ClosureType(_)
2544 | UnqualifiedName::ABITag(_) => false,
2545 }
2546 }
2547 }
2548
2549 impl UnqualifiedName {
2550 #[inline]
starts_with(byte: u8, input: &IndexStr) -> bool2551 fn starts_with(byte: u8, input: &IndexStr) -> bool {
2552 byte == b'L'
2553 || OperatorName::starts_with(byte)
2554 || CtorDtorName::starts_with(byte)
2555 || SourceName::starts_with(byte)
2556 || UnnamedTypeName::starts_with(byte)
2557 || TaggedName::starts_with(byte)
2558 || ClosureTypeName::starts_with(byte, input)
2559 }
2560
accepts_double_colon(&self) -> bool2561 fn accepts_double_colon(&self) -> bool {
2562 match *self {
2563 UnqualifiedName::Operator(_)
2564 | UnqualifiedName::CtorDtor(_)
2565 | UnqualifiedName::Source(_)
2566 | UnqualifiedName::LocalSourceName(..)
2567 | UnqualifiedName::UnnamedType(_)
2568 | UnqualifiedName::ClosureType(_) => true,
2569 UnqualifiedName::ABITag(_) => false,
2570 }
2571 }
2572 }
2573
2574 /// The `<source-name>` non-terminal.
2575 ///
2576 /// ```text
2577 /// <source-name> ::= <positive length number> <identifier>
2578 /// ```
2579 #[derive(Clone, Debug, PartialEq, Eq)]
2580 pub struct SourceName(Identifier);
2581
2582 impl Parse for SourceName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(SourceName, IndexStr<'b>)>2583 fn parse<'a, 'b>(
2584 ctx: &'a ParseContext,
2585 subs: &'a mut SubstitutionTable,
2586 input: IndexStr<'b>,
2587 ) -> Result<(SourceName, IndexStr<'b>)> {
2588 try_begin_parse!("SourceName", ctx, input);
2589
2590 let (source_name_len, input) = parse_number(10, false, input)?;
2591 debug_assert!(source_name_len >= 0);
2592 if source_name_len == 0 {
2593 return Err(error::Error::UnexpectedText);
2594 }
2595
2596 let (head, tail) = match input.try_split_at(source_name_len as _) {
2597 Some((head, tail)) => (head, tail),
2598 None => return Err(error::Error::UnexpectedEnd),
2599 };
2600
2601 let (identifier, empty) = Identifier::parse(ctx, subs, head)?;
2602 if !empty.is_empty() {
2603 return Err(error::Error::UnexpectedText);
2604 }
2605
2606 let source_name = SourceName(identifier);
2607 Ok((source_name, tail))
2608 }
2609 }
2610
2611 impl<'subs> ArgScope<'subs, 'subs> for SourceName {
leaf_name(&'subs self) -> Result<LeafName<'subs>>2612 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
2613 Ok(LeafName::SourceName(self))
2614 }
2615
get_template_arg( &'subs self, _: usize, ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)>2616 fn get_template_arg(
2617 &'subs self,
2618 _: usize,
2619 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
2620 Err(error::Error::BadTemplateArgReference)
2621 }
2622
get_function_arg(&'subs self, _: usize) -> Result<&'subs Type>2623 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
2624 Err(error::Error::BadFunctionArgReference)
2625 }
2626 }
2627
2628 impl SourceName {
2629 #[inline]
starts_with(byte: u8) -> bool2630 fn starts_with(byte: u8) -> bool {
2631 byte == b'0' || (b'0' <= byte && byte <= b'9')
2632 }
2633 }
2634
2635 impl<'subs, W> Demangle<'subs, W> for SourceName
2636 where
2637 W: 'subs + DemangleWrite,
2638 {
2639 #[inline]
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result2640 fn demangle<'prev, 'ctx>(
2641 &'subs self,
2642 ctx: &'ctx mut DemangleContext<'subs, W>,
2643 scope: Option<ArgScopeStack<'prev, 'subs>>,
2644 ) -> fmt::Result {
2645 let ctx = try_begin_demangle!(self, ctx, scope);
2646
2647 self.0.demangle(ctx, scope)
2648 }
2649 }
2650
2651 /// The `<tagged-name>` non-terminal.
2652 ///
2653 /// ```text
2654 /// <tagged-name> ::= <name> B <source-name>
2655 /// ```
2656 #[derive(Clone, Debug, PartialEq, Eq)]
2657 pub struct TaggedName(SourceName);
2658
2659 impl Parse for TaggedName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(TaggedName, IndexStr<'b>)>2660 fn parse<'a, 'b>(
2661 ctx: &'a ParseContext,
2662 subs: &'a mut SubstitutionTable,
2663 input: IndexStr<'b>,
2664 ) -> Result<(TaggedName, IndexStr<'b>)> {
2665 try_begin_parse!("TaggedName", ctx, input);
2666
2667 let tail = consume(b"B", input)?;
2668 let (source_name, tail) = SourceName::parse(ctx, subs, tail)?;
2669 Ok((TaggedName(source_name), tail))
2670 }
2671 }
2672
2673 impl<'subs, W> Demangle<'subs, W> for TaggedName
2674 where
2675 W: 'subs + DemangleWrite,
2676 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result2677 fn demangle<'prev, 'ctx>(
2678 &'subs self,
2679 ctx: &'ctx mut DemangleContext<'subs, W>,
2680 scope: Option<ArgScopeStack<'prev, 'subs>>,
2681 ) -> fmt::Result {
2682 let ctx = try_begin_demangle!(self, ctx, scope);
2683
2684 write!(ctx, "[abi:")?;
2685 self.0.demangle(ctx, scope)?;
2686 write!(ctx, "]")
2687 }
2688 }
2689
2690 impl TaggedName {
2691 #[inline]
starts_with(byte: u8) -> bool2692 fn starts_with(byte: u8) -> bool {
2693 byte == b'B'
2694 }
2695 }
2696
2697 /// The `<identifier>` pseudo-terminal.
2698 ///
2699 /// ```text
2700 /// <identifier> ::= <unqualified source code identifier>
2701 /// ```
2702 ///
2703 /// > `<identifier>` is a pseudo-terminal representing the characters in the
2704 /// > unqualified identifier for the entity in the source code. This ABI does not
2705 /// > yet specify a mangling for identifiers containing characters outside of
2706 /// > `_A-Za-z0-9.`.
2707 ///
2708 /// Mangled symbols' identifiers also have `$` characters in the wild.
2709 #[derive(Clone, Debug, PartialEq, Eq)]
2710 pub struct Identifier {
2711 start: usize,
2712 end: usize,
2713 }
2714
2715 impl Parse for Identifier {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Identifier, IndexStr<'b>)>2716 fn parse<'a, 'b>(
2717 ctx: &'a ParseContext,
2718 _subs: &'a mut SubstitutionTable,
2719 input: IndexStr<'b>,
2720 ) -> Result<(Identifier, IndexStr<'b>)> {
2721 try_begin_parse!("Identifier", ctx, input);
2722
2723 if input.is_empty() {
2724 return Err(error::Error::UnexpectedEnd);
2725 }
2726
2727 let end = input
2728 .as_ref()
2729 .iter()
2730 .map(|&c| c as char)
2731 .take_while(|&c| c == '$' || c == '_' || c == '.' || c.is_digit(36))
2732 .count();
2733
2734 if end == 0 {
2735 return Err(error::Error::UnexpectedText);
2736 }
2737
2738 let tail = input.range_from(end..);
2739
2740 let identifier = Identifier {
2741 start: input.index(),
2742 end: tail.index(),
2743 };
2744
2745 Ok((identifier, tail))
2746 }
2747 }
2748
2749 impl<'subs, W> Demangle<'subs, W> for Identifier
2750 where
2751 W: 'subs + DemangleWrite,
2752 {
2753 #[inline]
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result2754 fn demangle<'prev, 'ctx>(
2755 &'subs self,
2756 ctx: &'ctx mut DemangleContext<'subs, W>,
2757 scope: Option<ArgScopeStack<'prev, 'subs>>,
2758 ) -> fmt::Result {
2759 let ctx = try_begin_demangle!(self, ctx, scope);
2760
2761 let ident = &ctx.input[self.start..self.end];
2762
2763 // Handle GCC's anonymous namespace mangling.
2764 let anon_namespace_prefix = b"_GLOBAL_";
2765 if ident.starts_with(anon_namespace_prefix)
2766 && ident.len() >= anon_namespace_prefix.len() + 2
2767 {
2768 let first = ident[anon_namespace_prefix.len()];
2769 let second = ident[anon_namespace_prefix.len() + 1];
2770
2771 match (first, second) {
2772 (b'.', b'N') | (b'_', b'N') | (b'$', b'N') => {
2773 write!(ctx, "(anonymous namespace)")?;
2774 return Ok(());
2775 }
2776 _ => {
2777 // Fall through.
2778 }
2779 }
2780 }
2781
2782 let source_name = String::from_utf8_lossy(ident);
2783 ctx.set_source_name(self.start, self.end);
2784 write!(ctx, "{}", source_name)?;
2785 Ok(())
2786 }
2787 }
2788
2789 /// The `<clone-type-identifier>` pseudo-terminal.
2790 ///
2791 /// ```text
2792 /// <clone-type-identifier> ::= <unqualified source code identifier>
2793 /// ```
2794 #[derive(Clone, Debug, PartialEq, Eq)]
2795 pub struct CloneTypeIdentifier {
2796 start: usize,
2797 end: usize,
2798 }
2799
2800 impl Parse for CloneTypeIdentifier {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(CloneTypeIdentifier, IndexStr<'b>)>2801 fn parse<'a, 'b>(
2802 ctx: &'a ParseContext,
2803 _subs: &'a mut SubstitutionTable,
2804 input: IndexStr<'b>,
2805 ) -> Result<(CloneTypeIdentifier, IndexStr<'b>)> {
2806 try_begin_parse!("CloneTypeIdentifier", ctx, input);
2807
2808 if input.is_empty() {
2809 return Err(error::Error::UnexpectedEnd);
2810 }
2811
2812 let end = input
2813 .as_ref()
2814 .iter()
2815 .map(|&c| c as char)
2816 .take_while(|&c| c == '$' || c == '_' || c.is_digit(36))
2817 .count();
2818
2819 if end == 0 {
2820 return Err(error::Error::UnexpectedText);
2821 }
2822
2823 let tail = input.range_from(end..);
2824
2825 let identifier = CloneTypeIdentifier {
2826 start: input.index(),
2827 end: tail.index(),
2828 };
2829
2830 Ok((identifier, tail))
2831 }
2832 }
2833
2834 impl<'subs, W> Demangle<'subs, W> for CloneTypeIdentifier
2835 where
2836 W: 'subs + DemangleWrite,
2837 {
2838 #[inline]
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result2839 fn demangle<'prev, 'ctx>(
2840 &'subs self,
2841 ctx: &'ctx mut DemangleContext<'subs, W>,
2842 scope: Option<ArgScopeStack<'prev, 'subs>>,
2843 ) -> fmt::Result {
2844 let ctx = try_begin_demangle!(self, ctx, scope);
2845
2846 let ident = &ctx.input[self.start..self.end];
2847
2848 let source_name = String::from_utf8_lossy(ident);
2849 ctx.set_source_name(self.start, self.end);
2850 write!(ctx, " .{}", source_name)?;
2851 Ok(())
2852 }
2853 }
2854
2855 /// The `<number>` production.
2856 ///
2857 /// ```text
2858 /// <number> ::= [n] <non-negative decimal integer>
2859 /// ```
2860 type Number = isize;
2861
2862 impl Parse for Number {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(isize, IndexStr<'b>)>2863 fn parse<'a, 'b>(
2864 ctx: &'a ParseContext,
2865 _subs: &'a mut SubstitutionTable,
2866 input: IndexStr<'b>,
2867 ) -> Result<(isize, IndexStr<'b>)> {
2868 try_begin_parse!("Number", ctx, input);
2869 parse_number(10, true, input)
2870 }
2871 }
2872
2873 /// A <seq-id> production encoding a base-36 positive number.
2874 ///
2875 /// ```text
2876 /// <seq-id> ::= <0-9A-Z>+
2877 /// ```
2878 #[derive(Clone, Debug, PartialEq, Eq)]
2879 pub struct SeqId(usize);
2880
2881 impl Parse for SeqId {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(SeqId, IndexStr<'b>)>2882 fn parse<'a, 'b>(
2883 ctx: &'a ParseContext,
2884 _subs: &'a mut SubstitutionTable,
2885 input: IndexStr<'b>,
2886 ) -> Result<(SeqId, IndexStr<'b>)> {
2887 try_begin_parse!("SeqId", ctx, input);
2888
2889 parse_number(36, false, input).map(|(num, tail)| (SeqId(num as _), tail))
2890 }
2891 }
2892
2893 /// The `<operator-name>` production.
2894 ///
2895 /// ```text
2896 /// <operator-name> ::= <simple-operator-name>
2897 /// ::= cv <type> # (cast)
2898 /// ::= li <source-name> # operator ""
2899 /// ::= v <digit> <source-name> # vendor extended operator
2900 /// ```
2901 #[derive(Clone, Debug, PartialEq, Eq)]
2902 pub enum OperatorName {
2903 /// A simple operator name.
2904 Simple(SimpleOperatorName),
2905
2906 /// A type cast.
2907 Cast(TypeHandle),
2908
2909 /// A type conversion.
2910 Conversion(TypeHandle),
2911
2912 /// Operator literal, ie `operator ""`.
2913 Literal(SourceName),
2914
2915 /// A non-standard, vendor extension operator.
2916 VendorExtension(u8, SourceName),
2917 }
2918
2919 impl OperatorName {
starts_with(byte: u8) -> bool2920 fn starts_with(byte: u8) -> bool {
2921 byte == b'c' || byte == b'l' || byte == b'v' || SimpleOperatorName::starts_with(byte)
2922 }
2923
arity(&self) -> u82924 fn arity(&self) -> u8 {
2925 match self {
2926 &OperatorName::Cast(_) | &OperatorName::Conversion(_) | &OperatorName::Literal(_) => 1,
2927 &OperatorName::Simple(ref s) => s.arity(),
2928 &OperatorName::VendorExtension(arity, _) => arity,
2929 }
2930 }
2931
parse_from_expr<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Expression, IndexStr<'b>)>2932 fn parse_from_expr<'a, 'b>(
2933 ctx: &'a ParseContext,
2934 subs: &'a mut SubstitutionTable,
2935 input: IndexStr<'b>,
2936 ) -> Result<(Expression, IndexStr<'b>)> {
2937 let (operator, tail) = OperatorName::parse_internal(ctx, subs, input, true)?;
2938
2939 let arity = operator.arity();
2940 if arity == 1 {
2941 let (first, tail) = Expression::parse(ctx, subs, tail)?;
2942 let expr = Expression::Unary(operator, Box::new(first));
2943 Ok((expr, tail))
2944 } else if arity == 2 {
2945 let (first, tail) = Expression::parse(ctx, subs, tail)?;
2946 let (second, tail) = Expression::parse(ctx, subs, tail)?;
2947 let expr = Expression::Binary(operator, Box::new(first), Box::new(second));
2948 Ok((expr, tail))
2949 } else if arity == 3 {
2950 let (first, tail) = Expression::parse(ctx, subs, tail)?;
2951 let (second, tail) = Expression::parse(ctx, subs, tail)?;
2952 let (third, tail) = Expression::parse(ctx, subs, tail)?;
2953 let expr =
2954 Expression::Ternary(operator, Box::new(first), Box::new(second), Box::new(third));
2955 Ok((expr, tail))
2956 } else {
2957 Err(error::Error::UnexpectedText)
2958 }
2959 }
2960
parse_internal<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, from_expr: bool, ) -> Result<(OperatorName, IndexStr<'b>)>2961 fn parse_internal<'a, 'b>(
2962 ctx: &'a ParseContext,
2963 subs: &'a mut SubstitutionTable,
2964 input: IndexStr<'b>,
2965 from_expr: bool,
2966 ) -> Result<(OperatorName, IndexStr<'b>)> {
2967 try_begin_parse!("OperatorName", ctx, input);
2968
2969 if let Ok((simple, tail)) = SimpleOperatorName::parse(ctx, subs, input) {
2970 return Ok((OperatorName::Simple(simple), tail));
2971 }
2972
2973 if let Ok(tail) = consume(b"cv", input) {
2974 // If we came through the expression path, we're a cast. If not,
2975 // we're a conversion.
2976 let previously_in_conversion = ctx.set_in_conversion(!from_expr);
2977 let parse_result = TypeHandle::parse(ctx, subs, tail);
2978 ctx.set_in_conversion(previously_in_conversion);
2979 let (ty, tail) = parse_result?;
2980 if from_expr {
2981 return Ok((OperatorName::Cast(ty), tail));
2982 } else {
2983 return Ok((OperatorName::Conversion(ty), tail));
2984 }
2985 }
2986
2987 if let Ok(tail) = consume(b"li", input) {
2988 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
2989 return Ok((OperatorName::Literal(name), tail));
2990 }
2991
2992 let tail = consume(b"v", input)?;
2993 let (arity, tail) = match tail.peek() {
2994 Some(c) if b'0' <= c && c <= b'9' => (c - b'0', tail.range_from(1..)),
2995 None => return Err(error::Error::UnexpectedEnd),
2996 _ => return Err(error::Error::UnexpectedText),
2997 };
2998 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
2999 Ok((OperatorName::VendorExtension(arity, name), tail))
3000 }
3001 }
3002
3003 impl Parse for OperatorName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(OperatorName, IndexStr<'b>)>3004 fn parse<'a, 'b>(
3005 ctx: &'a ParseContext,
3006 subs: &'a mut SubstitutionTable,
3007 input: IndexStr<'b>,
3008 ) -> Result<(OperatorName, IndexStr<'b>)> {
3009 OperatorName::parse_internal(ctx, subs, input, false)
3010 }
3011 }
3012
3013 impl<'subs, W> Demangle<'subs, W> for OperatorName
3014 where
3015 W: 'subs + DemangleWrite,
3016 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result3017 fn demangle<'prev, 'ctx>(
3018 &'subs self,
3019 ctx: &'ctx mut DemangleContext<'subs, W>,
3020 scope: Option<ArgScopeStack<'prev, 'subs>>,
3021 ) -> fmt::Result {
3022 let ctx = try_begin_demangle!(self, ctx, scope);
3023
3024 match *self {
3025 OperatorName::Simple(ref simple) => {
3026 match *simple {
3027 SimpleOperatorName::New
3028 | SimpleOperatorName::NewArray
3029 | SimpleOperatorName::Delete
3030 | SimpleOperatorName::DeleteArray => {
3031 ctx.ensure_space()?;
3032 }
3033 _ => {}
3034 }
3035 simple.demangle(ctx, scope)
3036 }
3037 OperatorName::Cast(ref ty) | OperatorName::Conversion(ref ty) => {
3038 ctx.ensure_space()?;
3039
3040 // Cast operators can refer to template arguments before they
3041 // actually appear in the AST, so we go traverse down the tree
3042 // and fetch them if they exist.
3043 let scope = ty
3044 .get_template_args(ctx.subs)
3045 .map_or(scope, |args| scope.push(args));
3046
3047 ty.demangle(ctx, scope)?;
3048 Ok(())
3049 }
3050 OperatorName::Literal(ref name) => {
3051 name.demangle(ctx, scope)?;
3052 write!(ctx, "::operator \"\"")?;
3053 Ok(())
3054 }
3055 OperatorName::VendorExtension(arity, ref name) => {
3056 // TODO: no idea how this should be demangled...
3057 name.demangle(ctx, scope)?;
3058 write!(ctx, "::operator {}", arity)?;
3059 Ok(())
3060 }
3061 }
3062 }
3063 }
3064
3065 define_vocabulary! {
3066 /// The `<simple-operator-name>` production.
3067 #[derive(Clone, Debug, PartialEq, Eq)]
3068 pub enum SimpleOperatorName {
3069 New (b"nw", "new", 3),
3070 NewArray (b"na", "new[]", 3),
3071 Delete (b"dl", "delete", 1),
3072 DeleteArray (b"da", "delete[]", 1),
3073 UnaryPlus (b"ps", "+", 1),
3074 Neg (b"ng", "-", 1),
3075 AddressOf (b"ad", "&", 1),
3076 Deref (b"de", "*", 1),
3077 BitNot (b"co", "~", 1),
3078 Add (b"pl", "+", 2),
3079 Sub (b"mi", "-", 2),
3080 Mul (b"ml", "*", 2),
3081 Div (b"dv", "/", 2),
3082 Rem (b"rm", "%", 2),
3083 BitAnd (b"an", "&", 2),
3084 BitOr (b"or", "|", 2),
3085 BitXor (b"eo", "^", 2),
3086 Assign (b"aS", "=", 2),
3087 AddAssign (b"pL", "+=", 2),
3088 SubAssign (b"mI", "-=", 2),
3089 MulAssign (b"mL", "*=", 2),
3090 DivAssign (b"dV", "/=", 2),
3091 RemAssign (b"rM", "%=", 2),
3092 BitAndAssign (b"aN", "&=", 2),
3093 BitOrAssign (b"oR", "|=", 2),
3094 BitXorAssign (b"eO", "^=", 2),
3095 Shl (b"ls", "<<", 2),
3096 Shr (b"rs", ">>", 2),
3097 ShlAssign (b"lS", "<<=", 2),
3098 ShrAssign (b"rS", ">>=", 2),
3099 Eq (b"eq", "==", 2),
3100 Ne (b"ne", "!=", 2),
3101 Less (b"lt", "<", 2),
3102 Greater (b"gt", ">", 2),
3103 LessEq (b"le", "<=", 2),
3104 GreaterEq (b"ge", ">=", 2),
3105 Not (b"nt", "!", 1),
3106 LogicalAnd (b"aa", "&&", 2),
3107 LogicalOr (b"oo", "||", 2),
3108 PostInc (b"pp", "++", 1), // (postfix in <expression> context)
3109 PostDec (b"mm", "--", 1), // (postfix in <expression> context)
3110 Comma (b"cm", ",", 2),
3111 DerefMemberPtr (b"pm", "->*", 2),
3112 DerefMember (b"pt", "->", 2),
3113 Call (b"cl", "()", 2),
3114 Index (b"ix", "[]", 2),
3115 Question (b"qu", "?:", 3),
3116 Spaceship (b"ss", "<=>", 2)
3117 }
3118
3119 impl SimpleOperatorName {
3120 // Automatically implemented by define_vocabulary!
3121 fn arity(&self) -> u8;
3122 }
3123 }
3124
3125 /// The `<call-offset>` production.
3126 ///
3127 /// ```text
3128 /// <call-offset> ::= h <nv-offset> _
3129 /// ::= v <v-offset> _
3130 /// ```
3131 #[derive(Clone, Debug, PartialEq, Eq)]
3132 pub enum CallOffset {
3133 /// A non-virtual offset.
3134 NonVirtual(NvOffset),
3135 /// A virtual offset.
3136 Virtual(VOffset),
3137 }
3138
3139 impl Parse for CallOffset {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(CallOffset, IndexStr<'b>)>3140 fn parse<'a, 'b>(
3141 ctx: &'a ParseContext,
3142 subs: &'a mut SubstitutionTable,
3143 input: IndexStr<'b>,
3144 ) -> Result<(CallOffset, IndexStr<'b>)> {
3145 try_begin_parse!("CallOffset", ctx, input);
3146
3147 if input.is_empty() {
3148 return Err(error::Error::UnexpectedEnd);
3149 }
3150
3151 if let Ok(tail) = consume(b"h", input) {
3152 let (offset, tail) = NvOffset::parse(ctx, subs, tail)?;
3153 let tail = consume(b"_", tail)?;
3154 return Ok((CallOffset::NonVirtual(offset), tail));
3155 }
3156
3157 if let Ok(tail) = consume(b"v", input) {
3158 let (offset, tail) = VOffset::parse(ctx, subs, tail)?;
3159 let tail = consume(b"_", tail)?;
3160 return Ok((CallOffset::Virtual(offset), tail));
3161 }
3162
3163 Err(error::Error::UnexpectedText)
3164 }
3165 }
3166
3167 impl<'subs, W> Demangle<'subs, W> for CallOffset
3168 where
3169 W: 'subs + DemangleWrite,
3170 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result3171 fn demangle<'prev, 'ctx>(
3172 &'subs self,
3173 ctx: &'ctx mut DemangleContext<'subs, W>,
3174 scope: Option<ArgScopeStack<'prev, 'subs>>,
3175 ) -> fmt::Result {
3176 let ctx = try_begin_demangle!(self, ctx, scope);
3177
3178 match *self {
3179 CallOffset::NonVirtual(NvOffset(offset)) => {
3180 write!(ctx, "{{offset({})}}", offset)?;
3181 }
3182 CallOffset::Virtual(VOffset(vbase, vcall)) => {
3183 write!(ctx, "{{virtual offset({}, {})}}", vbase, vcall)?;
3184 }
3185 }
3186 Ok(())
3187 }
3188 }
3189
3190 /// A non-virtual offset, as described by the <nv-offset> production.
3191 ///
3192 /// ```text
3193 /// <nv-offset> ::= <offset number>
3194 /// ```
3195 #[derive(Clone, Debug, PartialEq, Eq)]
3196 pub struct NvOffset(isize);
3197
3198 impl Parse for NvOffset {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(NvOffset, IndexStr<'b>)>3199 fn parse<'a, 'b>(
3200 ctx: &'a ParseContext,
3201 subs: &'a mut SubstitutionTable,
3202 input: IndexStr<'b>,
3203 ) -> Result<(NvOffset, IndexStr<'b>)> {
3204 try_begin_parse!("NvOffset", ctx, input);
3205
3206 Number::parse(ctx, subs, input).map(|(num, tail)| (NvOffset(num), tail))
3207 }
3208 }
3209
3210 /// A virtual offset, as described by the <v-offset> production.
3211 ///
3212 /// ```text
3213 /// <v-offset> ::= <offset number> _ <virtual offset number>
3214 /// ```
3215 #[derive(Clone, Debug, PartialEq, Eq)]
3216 pub struct VOffset(isize, isize);
3217
3218 impl Parse for VOffset {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(VOffset, IndexStr<'b>)>3219 fn parse<'a, 'b>(
3220 ctx: &'a ParseContext,
3221 subs: &'a mut SubstitutionTable,
3222 input: IndexStr<'b>,
3223 ) -> Result<(VOffset, IndexStr<'b>)> {
3224 try_begin_parse!("VOffset", ctx, input);
3225
3226 let (offset, tail) = Number::parse(ctx, subs, input)?;
3227 let tail = consume(b"_", tail)?;
3228 let (virtual_offset, tail) = Number::parse(ctx, subs, tail)?;
3229 Ok((VOffset(offset, virtual_offset), tail))
3230 }
3231 }
3232
3233 /// The `<ctor-dtor-name>` production.
3234 ///
3235 /// ```text
3236 /// <ctor-dtor-name> ::= C1 # complete object constructor
3237 /// ::= C2 # base object constructor
3238 /// ::= C3 # complete object allocating constructor
3239 /// ::= D0 # deleting destructor
3240 /// ::= D1 # complete object destructor
3241 /// ::= D2 # base object destructor
3242 /// ```
3243 ///
3244 /// GCC also emits a C4 constructor under some conditions when building
3245 /// an optimized binary. GCC's source says:
3246 ///
3247 /// ```
3248 /// /* This is the old-style "[unified]" constructor.
3249 /// In some cases, we may emit this function and call
3250 /// it from the clones in order to share code and save space. */
3251 /// ```
3252 ///
3253 /// Based on the GCC source we'll call this the "maybe in-charge constructor".
3254 /// Similarly, there is a D4 destructor, the "maybe in-charge destructor".
3255 #[derive(Clone, Debug, PartialEq, Eq)]
3256 pub enum CtorDtorName {
3257 /// "C1", the "complete object constructor"
3258 CompleteConstructor(Option<TypeHandle>),
3259 /// "C2", the "base object constructor"
3260 BaseConstructor(Option<TypeHandle>),
3261 /// "C3", the "complete object allocating constructor"
3262 CompleteAllocatingConstructor(Option<TypeHandle>),
3263 /// "C4", the "maybe in-charge constructor"
3264 MaybeInChargeConstructor(Option<TypeHandle>),
3265 /// "D0", the "deleting destructor"
3266 DeletingDestructor,
3267 /// "D1", the "complete object destructor"
3268 CompleteDestructor,
3269 /// "D2", the "base object destructor"
3270 BaseDestructor,
3271 /// "D4", the "maybe in-charge destructor"
3272 MaybeInChargeDestructor,
3273 }
3274
3275 impl CtorDtorName {
inheriting_mut(&mut self) -> &mut Option<TypeHandle>3276 fn inheriting_mut(&mut self) -> &mut Option<TypeHandle> {
3277 match self {
3278 CtorDtorName::CompleteConstructor(ref mut inheriting)
3279 | CtorDtorName::BaseConstructor(ref mut inheriting)
3280 | CtorDtorName::CompleteAllocatingConstructor(ref mut inheriting)
3281 | CtorDtorName::MaybeInChargeConstructor(ref mut inheriting) => inheriting,
3282 CtorDtorName::DeletingDestructor
3283 | CtorDtorName::CompleteDestructor
3284 | CtorDtorName::BaseDestructor
3285 | CtorDtorName::MaybeInChargeDestructor => unreachable!(),
3286 }
3287 }
3288 }
3289
3290 impl Parse for CtorDtorName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(CtorDtorName, IndexStr<'b>)>3291 fn parse<'a, 'b>(
3292 ctx: &'a ParseContext,
3293 subs: &'a mut SubstitutionTable,
3294 input: IndexStr<'b>,
3295 ) -> Result<(CtorDtorName, IndexStr<'b>)> {
3296 try_begin_parse!(stringify!(CtorDtorName), ctx, input);
3297
3298 match input.peek() {
3299 Some(b'C') => {
3300 let mut tail = consume(b"C", input)?;
3301 let inheriting = match tail.peek() {
3302 Some(b'I') => {
3303 tail = consume(b"I", tail)?;
3304 true
3305 }
3306 _ => false,
3307 };
3308
3309 let mut ctor_type: CtorDtorName = match tail
3310 .try_split_at(1)
3311 .as_ref()
3312 .map(|&(ref h, t)| (h.as_ref(), t))
3313 {
3314 None => Err(error::Error::UnexpectedEnd),
3315 Some((b"1", t)) => {
3316 tail = t;
3317 Ok(CtorDtorName::CompleteConstructor(None))
3318 }
3319 Some((b"2", t)) => {
3320 tail = t;
3321 Ok(CtorDtorName::BaseConstructor(None))
3322 }
3323 Some((b"3", t)) => {
3324 tail = t;
3325 Ok(CtorDtorName::CompleteAllocatingConstructor(None))
3326 }
3327 Some((b"4", t)) => {
3328 tail = t;
3329 Ok(CtorDtorName::MaybeInChargeConstructor(None))
3330 }
3331 _ => Err(error::Error::UnexpectedText),
3332 }?;
3333
3334 if inheriting {
3335 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3336 *ctor_type.inheriting_mut() = Some(ty);
3337 Ok((ctor_type, tail))
3338 } else {
3339 Ok((ctor_type, tail))
3340 }
3341 }
3342 Some(b'D') => {
3343 match input
3344 .try_split_at(2)
3345 .as_ref()
3346 .map(|&(ref h, t)| (h.as_ref(), t))
3347 {
3348 Some((b"D0", tail)) => Ok((CtorDtorName::DeletingDestructor, tail)),
3349 Some((b"D1", tail)) => Ok((CtorDtorName::CompleteDestructor, tail)),
3350 Some((b"D2", tail)) => Ok((CtorDtorName::BaseDestructor, tail)),
3351 Some((b"D4", tail)) => Ok((CtorDtorName::MaybeInChargeDestructor, tail)),
3352 _ => Err(error::Error::UnexpectedText),
3353 }
3354 }
3355 None => Err(error::Error::UnexpectedEnd),
3356 _ => Err(error::Error::UnexpectedText),
3357 }
3358 }
3359 }
3360
3361 impl<'subs, W> Demangle<'subs, W> for CtorDtorName
3362 where
3363 W: 'subs + DemangleWrite,
3364 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result3365 fn demangle<'prev, 'ctx>(
3366 &'subs self,
3367 ctx: &'ctx mut DemangleContext<'subs, W>,
3368 scope: Option<ArgScopeStack<'prev, 'subs>>,
3369 ) -> fmt::Result {
3370 let ctx = try_begin_demangle!(self, ctx, scope);
3371
3372 let leaf = scope.leaf_name().map_err(|e| {
3373 log!("Error getting leaf name: {}", e);
3374 fmt::Error
3375 })?;
3376
3377 match *self {
3378 CtorDtorName::CompleteConstructor(ref inheriting)
3379 | CtorDtorName::BaseConstructor(ref inheriting)
3380 | CtorDtorName::CompleteAllocatingConstructor(ref inheriting)
3381 | CtorDtorName::MaybeInChargeConstructor(ref inheriting) => match inheriting {
3382 Some(ty) => ty
3383 .get_leaf_name(ctx.subs)
3384 .ok_or_else(|| {
3385 log!("Error getting leaf name: {:?}", ty);
3386 fmt::Error
3387 })?
3388 .demangle_as_leaf(ctx),
3389 None => leaf.demangle_as_leaf(ctx),
3390 },
3391 CtorDtorName::DeletingDestructor
3392 | CtorDtorName::CompleteDestructor
3393 | CtorDtorName::BaseDestructor
3394 | CtorDtorName::MaybeInChargeDestructor => {
3395 write!(ctx, "~")?;
3396 leaf.demangle_as_leaf(ctx)
3397 }
3398 }
3399 }
3400 }
3401
3402 impl CtorDtorName {
3403 #[inline]
starts_with(byte: u8) -> bool3404 fn starts_with(byte: u8) -> bool {
3405 byte == b'C' || byte == b'D'
3406 }
3407 }
3408
3409 /// The `<type>` production.
3410 ///
3411 /// ```text
3412 /// <type> ::= <builtin-type>
3413 /// ::= <function-type>
3414 /// ::= <class-enum-type>
3415 /// ::= <array-type>
3416 /// ::= <vector-type>
3417 /// ::= <pointer-to-member-type>
3418 /// ::= <template-param>
3419 /// ::= <template-template-param> <template-args>
3420 /// ::= <decltype>
3421 /// ::= <CV-qualifiers> <type>
3422 /// ::= P <type> # pointer-to
3423 /// ::= R <type> # reference-to
3424 /// ::= O <type> # rvalue reference-to (C++0x)
3425 /// ::= C <type> # complex pair (C 2000)
3426 /// ::= G <type> # imaginary (C 2000)
3427 /// ::= U <source-name> [<template-args>] <type> # vendor extended type qualifier
3428 /// ::= Dp <type> # pack expansion (C++0x)
3429 /// ::= <substitution>
3430 /// ```
3431 #[derive(Clone, Debug, PartialEq, Eq)]
3432 #[allow(clippy::large_enum_variant)]
3433 pub enum Type {
3434 /// A function type.
3435 Function(FunctionType),
3436
3437 /// A class, union, or enum type.
3438 ClassEnum(ClassEnumType),
3439
3440 /// An array type.
3441 Array(ArrayType),
3442
3443 /// A vector type.
3444 Vector(VectorType),
3445
3446 /// A pointer-to-member type.
3447 PointerToMember(PointerToMemberType),
3448
3449 /// A named template parameter type.
3450 TemplateParam(TemplateParam),
3451
3452 /// A template template type.
3453 TemplateTemplate(TemplateTemplateParamHandle, TemplateArgs),
3454
3455 /// A decltype.
3456 Decltype(Decltype),
3457
3458 /// A const-, restrict-, and/or volatile-qualified type.
3459 Qualified(CvQualifiers, TypeHandle),
3460
3461 /// A pointer to a type.
3462 PointerTo(TypeHandle),
3463
3464 /// An lvalue reference to a type.
3465 LvalueRef(TypeHandle),
3466
3467 /// An rvalue reference to a type.
3468 RvalueRef(TypeHandle),
3469
3470 /// A complex pair of the given type.
3471 Complex(TypeHandle),
3472
3473 /// An imaginary of the given type.
3474 Imaginary(TypeHandle),
3475
3476 /// A vendor extended type qualifier.
3477 VendorExtension(SourceName, Option<TemplateArgs>, TypeHandle),
3478
3479 /// A pack expansion.
3480 PackExpansion(TypeHandle),
3481 }
3482
3483 define_handle! {
3484 /// A reference to a parsed `Type` production.
3485 pub enum TypeHandle {
3486 /// A builtin type. These don't end up in the substitutions table.
3487 extra Builtin(BuiltinType),
3488
3489 /// A CV-qualified builtin type. These don't end up in the table either.
3490 extra QualifiedBuiltin(QualifiedBuiltin),
3491 }
3492 }
3493
3494 impl TypeHandle {
is_void(&self) -> bool3495 fn is_void(&self) -> bool {
3496 match *self {
3497 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Void)) => true,
3498 _ => false,
3499 }
3500 }
3501 }
3502
3503 impl Parse for TypeHandle {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(TypeHandle, IndexStr<'b>)>3504 fn parse<'a, 'b>(
3505 ctx: &'a ParseContext,
3506 subs: &'a mut SubstitutionTable,
3507 input: IndexStr<'b>,
3508 ) -> Result<(TypeHandle, IndexStr<'b>)> {
3509 try_begin_parse!("TypeHandle", ctx, input);
3510
3511 /// Insert the given type into the substitution table, and return a
3512 /// handle referencing the index in the table where it ended up.
3513 fn insert_and_return_handle<'a, 'b>(
3514 ty: Type,
3515 subs: &'a mut SubstitutionTable,
3516 tail: IndexStr<'b>,
3517 ) -> Result<(TypeHandle, IndexStr<'b>)> {
3518 let ty = Substitutable::Type(ty);
3519 let idx = subs.insert(ty);
3520 let handle = TypeHandle::BackReference(idx);
3521 Ok((handle, tail))
3522 }
3523
3524 if let Ok((builtin, tail)) = BuiltinType::parse(ctx, subs, input) {
3525 // Builtin types are one of two exceptions that do not end up in the
3526 // substitutions table.
3527 let handle = TypeHandle::Builtin(builtin);
3528 return Ok((handle, tail));
3529 }
3530
3531 if let Ok((ty, tail)) = ClassEnumType::parse(ctx, subs, input) {
3532 let ty = Type::ClassEnum(ty);
3533 return insert_and_return_handle(ty, subs, tail);
3534 }
3535
3536 if let Ok((sub, tail)) = Substitution::parse(ctx, subs, input) {
3537 // If we see an 'I', then this is actually a substitution for a
3538 // <template-template-param>, and the template args are what
3539 // follows. Throw away what we just parsed, and re-parse it in
3540 // `TemplateTemplateParamHandle::parse` for now, but it would be
3541 // nice not to duplicate work we've already done.
3542 if tail.peek() != Some(b'I') {
3543 match sub {
3544 Substitution::WellKnown(component) => {
3545 return Ok((TypeHandle::WellKnown(component), tail));
3546 }
3547 Substitution::BackReference(idx) => {
3548 // TODO: should this check if the back reference actually points
3549 // to a <type>?
3550 return Ok((TypeHandle::BackReference(idx), tail));
3551 }
3552 }
3553 }
3554 }
3555
3556 if let Ok((funty, tail)) = FunctionType::parse(ctx, subs, input) {
3557 let ty = Type::Function(funty);
3558 return insert_and_return_handle(ty, subs, tail);
3559 }
3560
3561 if let Ok((ty, tail)) = ArrayType::parse(ctx, subs, input) {
3562 let ty = Type::Array(ty);
3563 return insert_and_return_handle(ty, subs, tail);
3564 }
3565
3566 if let Ok((ty, tail)) = VectorType::parse(ctx, subs, input) {
3567 let ty = Type::Vector(ty);
3568 return insert_and_return_handle(ty, subs, tail);
3569 }
3570
3571 if let Ok((ty, tail)) = PointerToMemberType::parse(ctx, subs, input) {
3572 let ty = Type::PointerToMember(ty);
3573 return insert_and_return_handle(ty, subs, tail);
3574 }
3575
3576 if let Ok((param, tail)) = TemplateParam::parse(ctx, subs, input) {
3577 // Same situation as with `Substitution::parse` at the top of this
3578 // function: this is actually a <template-template-param> and
3579 // <template-args>.
3580 if tail.peek() != Some(b'I') {
3581 let ty = Type::TemplateParam(param);
3582 return insert_and_return_handle(ty, subs, tail);
3583 } else if ctx.in_conversion() {
3584 // This may be <template-template-param> <template-args>.
3585 // But if we're here for a conversion operator, that's only
3586 // possible if the grammar looks like:
3587 //
3588 // <nested-name>
3589 // -> <source-name> cv <template-template-param> <template-args> <template-args>
3590 //
3591 // That is, there must be *another* <template-args> production after ours.
3592 // If there isn't one, then this really is a <template-param>.
3593 //
3594 // NB: Parsing a <template-args> production may modify the substitutions
3595 // table, so we need to avoid contaminating the official copy.
3596 let mut tmp_subs = subs.clone();
3597 if let Ok((_, new_tail)) = TemplateArgs::parse(ctx, &mut tmp_subs, tail) {
3598 if new_tail.peek() != Some(b'I') {
3599 // Don't consume the TemplateArgs.
3600 let ty = Type::TemplateParam(param);
3601 return insert_and_return_handle(ty, subs, tail);
3602 }
3603 // We really do have a <template-template-param>. Fall through.
3604 // NB: We can't use the arguments we just parsed because a
3605 // TemplateTemplateParam is substitutable, and if we use it
3606 // any substitutions in the arguments will come *before* it,
3607 // putting the substitution table out of order.
3608 }
3609 }
3610 }
3611
3612 if let Ok((ttp, tail)) = TemplateTemplateParamHandle::parse(ctx, subs, input) {
3613 let (args, tail) = TemplateArgs::parse(ctx, subs, tail)?;
3614 let ty = Type::TemplateTemplate(ttp, args);
3615 return insert_and_return_handle(ty, subs, tail);
3616 }
3617
3618 if let Ok((param, tail)) = Decltype::parse(ctx, subs, input) {
3619 let ty = Type::Decltype(param);
3620 return insert_and_return_handle(ty, subs, tail);
3621 }
3622
3623 if let Ok((qualifiers, tail)) = CvQualifiers::parse(ctx, subs, input) {
3624 // CvQualifiers can parse successfully without consuming any input,
3625 // but we don't want to recurse unless we know we did consume some
3626 // input, lest we go into an infinite loop and blow the stack.
3627 if tail.len() < input.len() {
3628 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3629 let ty = Type::Qualified(qualifiers, ty);
3630 return insert_and_return_handle(ty, subs, tail);
3631 }
3632 }
3633
3634 if let Ok(tail) = consume(b"P", input) {
3635 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3636 let ty = Type::PointerTo(ty);
3637 return insert_and_return_handle(ty, subs, tail);
3638 }
3639
3640 if let Ok(tail) = consume(b"R", input) {
3641 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3642 let ty = Type::LvalueRef(ty);
3643 return insert_and_return_handle(ty, subs, tail);
3644 }
3645
3646 if let Ok(tail) = consume(b"O", input) {
3647 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3648 let ty = Type::RvalueRef(ty);
3649 return insert_and_return_handle(ty, subs, tail);
3650 }
3651
3652 if let Ok(tail) = consume(b"C", input) {
3653 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3654 let ty = Type::Complex(ty);
3655 return insert_and_return_handle(ty, subs, tail);
3656 }
3657
3658 if let Ok(tail) = consume(b"G", input) {
3659 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3660 let ty = Type::Imaginary(ty);
3661 return insert_and_return_handle(ty, subs, tail);
3662 }
3663
3664 if let Ok(tail) = consume(b"U", input) {
3665 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
3666 let (args, tail) = if let Ok((args, tail)) = TemplateArgs::parse(ctx, subs, tail) {
3667 (Some(args), tail)
3668 } else {
3669 (None, tail)
3670 };
3671 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3672 let ty = Type::VendorExtension(name, args, ty);
3673 return insert_and_return_handle(ty, subs, tail);
3674 }
3675
3676 let tail = consume(b"Dp", input)?;
3677 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3678 let ty = Type::PackExpansion(ty);
3679 insert_and_return_handle(ty, subs, tail)
3680 }
3681 }
3682
3683 impl GetTemplateArgs for TypeHandle {
get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>3684 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
3685 subs.get_type(self)
3686 .and_then(|ty| ty.get_template_args(subs))
3687 }
3688 }
3689
3690 impl<'subs, W> Demangle<'subs, W> for Type
3691 where
3692 W: 'subs + DemangleWrite,
3693 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result3694 fn demangle<'prev, 'ctx>(
3695 &'subs self,
3696 ctx: &'ctx mut DemangleContext<'subs, W>,
3697 scope: Option<ArgScopeStack<'prev, 'subs>>,
3698 ) -> fmt::Result {
3699 let ctx = try_begin_demangle!(self, ctx, scope);
3700
3701 match *self {
3702 Type::Function(ref func_ty) => func_ty.demangle(ctx, scope),
3703 Type::ClassEnum(ref cls_enum_ty) => cls_enum_ty.demangle(ctx, scope),
3704 Type::Array(ref array_ty) => array_ty.demangle(ctx, scope),
3705 Type::Vector(ref vector_ty) => vector_ty.demangle(ctx, scope),
3706 Type::PointerToMember(ref ptm) => ptm.demangle(ctx, scope),
3707 Type::TemplateParam(ref param) => param.demangle(ctx, scope),
3708 Type::TemplateTemplate(ref tt_param, ref args) => {
3709 tt_param.demangle(ctx, scope)?;
3710 args.demangle(ctx, scope)
3711 }
3712 Type::Decltype(ref dt) => dt.demangle(ctx, scope),
3713 Type::Qualified(_, ref ty) => {
3714 ctx.push_inner(self);
3715 ty.demangle(ctx, scope)?;
3716 if ctx.pop_inner_if(self) {
3717 self.demangle_as_inner(ctx, scope)?;
3718 }
3719 Ok(())
3720 }
3721 Type::PointerTo(ref ty) | Type::LvalueRef(ref ty) | Type::RvalueRef(ref ty) => {
3722 ctx.push_inner(self);
3723 ty.demangle(ctx, scope)?;
3724 if ctx.pop_inner_if(self) {
3725 self.demangle_as_inner(ctx, scope)?;
3726 }
3727 Ok(())
3728 }
3729 Type::Complex(ref ty) => {
3730 ty.demangle(ctx, scope)?;
3731 write!(ctx, " complex")?;
3732 Ok(())
3733 }
3734 Type::Imaginary(ref ty) => {
3735 ty.demangle(ctx, scope)?;
3736 write!(ctx, " imaginary")?;
3737 Ok(())
3738 }
3739 Type::VendorExtension(ref name, ref template_args, ref ty) => {
3740 ty.demangle(ctx, scope)?;
3741 write!(ctx, " ")?;
3742 name.demangle(ctx, scope)?;
3743 if let Some(ref args) = *template_args {
3744 args.demangle(ctx, scope)?;
3745 }
3746 Ok(())
3747 }
3748 Type::PackExpansion(ref ty) => {
3749 ty.demangle(ctx, scope)?;
3750 if !ctx.is_template_argument_pack {
3751 write!(ctx, "...")?;
3752 }
3753 Ok(())
3754 }
3755 }
3756 }
3757 }
3758
3759 impl<'subs, W> DemangleAsInner<'subs, W> for Type
3760 where
3761 W: 'subs + DemangleWrite,
3762 {
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result3763 fn demangle_as_inner<'prev, 'ctx>(
3764 &'subs self,
3765 ctx: &'ctx mut DemangleContext<'subs, W>,
3766 scope: Option<ArgScopeStack<'prev, 'subs>>,
3767 ) -> fmt::Result {
3768 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
3769
3770 match *self {
3771 Type::Qualified(ref quals, _) => quals.demangle_as_inner(ctx, scope),
3772 Type::PointerTo(_) => write!(ctx, "*"),
3773 Type::RvalueRef(_) => {
3774 while let Some(v) = ctx.inner.last().and_then(|ty| ty.downcast_to_type()) {
3775 match v {
3776 // Two r-value references combine into a single r-value reference
3777 // Consume any adjacent r-value references on the inner stack.
3778 Type::RvalueRef(_) => {
3779 ctx.inner.pop().unwrap();
3780 }
3781 // An r-value and an l-value reference combine into an l-value reference.
3782 // Skip printing this, and allow the LvalueRef implementation to
3783 // continue combining references.
3784 Type::LvalueRef(_) => return Ok(()),
3785 _ => break,
3786 }
3787 }
3788 write!(ctx, "&&")
3789 }
3790 Type::LvalueRef(_) => {
3791 while let Some(v) = ctx.inner.last().and_then(|ty| ty.downcast_to_type()) {
3792 match v {
3793 // An l-value reference combines with an r-value reference to form a
3794 // single l-value reference. Consume any adjacent r-value references
3795 // on the inner stack.
3796 Type::RvalueRef(_) => {
3797 ctx.inner.pop().unwrap();
3798 }
3799 // Two l-value references combine to form a single l-value reference.
3800 // Skip printing this, and allow the LvalueRef implementation for
3801 // the next l-value reference to continue combining references.
3802 Type::LvalueRef(_) => return Ok(()),
3803 _ => break,
3804 }
3805 }
3806 write!(ctx, "&")
3807 }
3808 ref otherwise => {
3809 unreachable!(
3810 "We shouldn't ever put any other types on the inner stack: {:?}",
3811 otherwise
3812 );
3813 }
3814 }
3815 }
3816
downcast_to_type(&self) -> Option<&Type>3817 fn downcast_to_type(&self) -> Option<&Type> {
3818 Some(self)
3819 }
3820
downcast_to_function_type(&self) -> Option<&FunctionType>3821 fn downcast_to_function_type(&self) -> Option<&FunctionType> {
3822 if let Type::Function(ref f) = *self {
3823 Some(f)
3824 } else {
3825 None
3826 }
3827 }
3828
downcast_to_array_type(&self) -> Option<&ArrayType>3829 fn downcast_to_array_type(&self) -> Option<&ArrayType> {
3830 if let Type::Array(ref arr) = *self {
3831 Some(arr)
3832 } else {
3833 None
3834 }
3835 }
3836
downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType>3837 fn downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType> {
3838 if let Type::PointerToMember(ref ptm) = *self {
3839 Some(ptm)
3840 } else {
3841 None
3842 }
3843 }
3844
is_qualified(&self) -> bool3845 fn is_qualified(&self) -> bool {
3846 match *self {
3847 Type::Qualified(..) => true,
3848 _ => false,
3849 }
3850 }
3851 }
3852
3853 impl GetTemplateArgs for Type {
get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>3854 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
3855 // TODO: This should probably recurse through all the nested type
3856 // handles too.
3857
3858 match *self {
3859 Type::VendorExtension(_, Some(ref args), _) | Type::TemplateTemplate(_, ref args) => {
3860 Some(args)
3861 }
3862 Type::PointerTo(ref ty) | Type::LvalueRef(ref ty) | Type::RvalueRef(ref ty) => {
3863 ty.get_template_args(subs)
3864 }
3865 _ => None,
3866 }
3867 }
3868 }
3869
3870 impl<'a> GetLeafName<'a> for Type {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>3871 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
3872 match *self {
3873 Type::ClassEnum(ref cls_enum_ty) => cls_enum_ty.get_leaf_name(subs),
3874 _ => None,
3875 }
3876 }
3877 }
3878
3879 /// The `<CV-qualifiers>` production.
3880 ///
3881 /// ```text
3882 /// <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
3883 /// ```
3884 #[derive(Clone, Debug, Default, Hash, PartialEq, Eq)]
3885 pub struct CvQualifiers {
3886 /// Is this `restrict` qualified?
3887 pub restrict: bool,
3888 /// Is this `volatile` qualified?
3889 pub volatile: bool,
3890 /// Is this `const` qualified?
3891 pub const_: bool,
3892 }
3893
3894 impl CvQualifiers {
3895 #[inline]
is_empty(&self) -> bool3896 fn is_empty(&self) -> bool {
3897 !self.restrict && !self.volatile && !self.const_
3898 }
3899 }
3900
3901 impl Parse for CvQualifiers {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(CvQualifiers, IndexStr<'b>)>3902 fn parse<'a, 'b>(
3903 ctx: &'a ParseContext,
3904 _subs: &'a mut SubstitutionTable,
3905 input: IndexStr<'b>,
3906 ) -> Result<(CvQualifiers, IndexStr<'b>)> {
3907 try_begin_parse!("CvQualifiers", ctx, input);
3908
3909 let (restrict, tail) = if let Ok(tail) = consume(b"r", input) {
3910 (true, tail)
3911 } else {
3912 (false, input)
3913 };
3914
3915 let (volatile, tail) = if let Ok(tail) = consume(b"V", tail) {
3916 (true, tail)
3917 } else {
3918 (false, tail)
3919 };
3920
3921 let (const_, tail) = if let Ok(tail) = consume(b"K", tail) {
3922 (true, tail)
3923 } else {
3924 (false, tail)
3925 };
3926
3927 let qualifiers = CvQualifiers {
3928 restrict: restrict,
3929 volatile: volatile,
3930 const_: const_,
3931 };
3932
3933 Ok((qualifiers, tail))
3934 }
3935 }
3936
3937 impl<'subs, W> Demangle<'subs, W> for CvQualifiers
3938 where
3939 W: 'subs + DemangleWrite,
3940 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result3941 fn demangle<'prev, 'ctx>(
3942 &'subs self,
3943 ctx: &'ctx mut DemangleContext<'subs, W>,
3944 scope: Option<ArgScopeStack<'prev, 'subs>>,
3945 ) -> fmt::Result {
3946 let ctx = try_begin_demangle!(self, ctx, scope);
3947
3948 if self.const_ {
3949 ctx.ensure_space()?;
3950 write!(ctx, "const")?;
3951 }
3952
3953 if self.volatile {
3954 ctx.ensure_space()?;
3955 write!(ctx, "volatile")?;
3956 }
3957
3958 if self.restrict {
3959 ctx.ensure_space()?;
3960 write!(ctx, "restrict")?;
3961 }
3962
3963 Ok(())
3964 }
3965 }
3966
3967 impl<'subs, W> DemangleAsInner<'subs, W> for CvQualifiers where W: 'subs + DemangleWrite {}
3968
3969 define_vocabulary! {
3970 /// A <ref-qualifier> production.
3971 ///
3972 /// ```text
3973 /// <ref-qualifier> ::= R # & ref-qualifier
3974 /// ::= O # && ref-qualifier
3975 /// ```
3976 #[derive(Clone, Debug, PartialEq, Eq)]
3977 pub enum RefQualifier {
3978 LValueRef(b"R", "&"),
3979 RValueRef(b"O", "&&")
3980 }
3981 }
3982
3983 define_vocabulary! {
3984 /// A one of the standard variants of the <builtin-type> production.
3985 ///
3986 /// ```text
3987 /// <builtin-type> ::= v # void
3988 /// ::= w # wchar_t
3989 /// ::= b # bool
3990 /// ::= c # char
3991 /// ::= a # signed char
3992 /// ::= h # unsigned char
3993 /// ::= s # short
3994 /// ::= t # unsigned short
3995 /// ::= i # int
3996 /// ::= j # unsigned int
3997 /// ::= l # long
3998 /// ::= m # unsigned long
3999 /// ::= x # long long, __int64
4000 /// ::= y # unsigned long long, __int64
4001 /// ::= n # __int128
4002 /// ::= o # unsigned __int128
4003 /// ::= f # float
4004 /// ::= d # double
4005 /// ::= e # long double, __float80
4006 /// ::= g # __float128
4007 /// ::= z # ellipsis
4008 /// ::= Dd # IEEE 754r decimal floating point (64 bits)
4009 /// ::= De # IEEE 754r decimal floating point (128 bits)
4010 /// ::= Df # IEEE 754r decimal floating point (32 bits)
4011 /// ::= Dh # IEEE 754r half-precision floating point (16 bits)
4012 /// ::= Di # char32_t
4013 /// ::= Ds # char16_t
4014 /// ::= Da # auto
4015 /// ::= Dc # decltype(auto)
4016 /// ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
4017 /// ```
4018 #[derive(Clone, Debug, PartialEq, Eq)]
4019 pub enum StandardBuiltinType {
4020 Void (b"v", "void"),
4021 Wchar (b"w", "wchar_t"),
4022 Bool (b"b", "bool"),
4023 Char (b"c", "char"),
4024 SignedChar (b"a", "signed char"),
4025 UnsignedChar (b"h", "unsigned char"),
4026 Short (b"s", "short"),
4027 UnsignedShort (b"t", "unsigned short"),
4028 Int (b"i", "int"),
4029 UnsignedInt (b"j", "unsigned int"),
4030 Long (b"l", "long"),
4031 UnsignedLong (b"m", "unsigned long"),
4032 LongLong (b"x", "long long"),
4033 UnsignedLongLong (b"y", "unsigned long long"),
4034 Int128 (b"n", "__int128"),
4035 Uint128 (b"o", "unsigned __int128"),
4036 Float (b"f", "float"),
4037 Double (b"d", "double"),
4038 LongDouble (b"e", "long double"),
4039 Float128 (b"g", "__float128"),
4040 Ellipsis (b"z", "..."),
4041 DecimalFloat64 (b"Dd", "decimal64"),
4042 DecimalFloat128 (b"De", "decimal128"),
4043 DecimalFloat32 (b"Df", "decimal32"),
4044 DecimalFloat16 (b"Dh", "half"),
4045 Char32 (b"Di", "char32_t"),
4046 Char16 (b"Ds", "char16_t"),
4047 Auto (b"Da", "auto"),
4048 Decltype (b"Dc", "decltype(auto)"),
4049 Nullptr (b"Dn", "std::nullptr_t")
4050 }
4051 }
4052
4053 /// The `<builtin-type>` production.
4054 #[derive(Clone, Debug, PartialEq, Eq)]
4055 pub enum BuiltinType {
4056 /// A standards compliant builtin type.
4057 Standard(StandardBuiltinType),
4058
4059 /// A non-standard, vendor extension type.
4060 ///
4061 /// ```text
4062 /// <builtin-type> ::= u <source-name> # vendor extended type
4063 /// ```
4064 Extension(SourceName),
4065 }
4066
4067 impl Parse for BuiltinType {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(BuiltinType, IndexStr<'b>)>4068 fn parse<'a, 'b>(
4069 ctx: &'a ParseContext,
4070 subs: &'a mut SubstitutionTable,
4071 input: IndexStr<'b>,
4072 ) -> Result<(BuiltinType, IndexStr<'b>)> {
4073 try_begin_parse!("BuiltinType", ctx, input);
4074
4075 if let Ok((ty, tail)) = StandardBuiltinType::parse(ctx, subs, input) {
4076 return Ok((BuiltinType::Standard(ty), tail));
4077 }
4078
4079 let tail = consume(b"u", input)?;
4080 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
4081 Ok((BuiltinType::Extension(name), tail))
4082 }
4083 }
4084
4085 impl<'subs, W> Demangle<'subs, W> for BuiltinType
4086 where
4087 W: 'subs + DemangleWrite,
4088 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4089 fn demangle<'prev, 'ctx>(
4090 &'subs self,
4091 ctx: &'ctx mut DemangleContext<'subs, W>,
4092 scope: Option<ArgScopeStack<'prev, 'subs>>,
4093 ) -> fmt::Result {
4094 let ctx = try_begin_demangle!(self, ctx, scope);
4095
4096 match *self {
4097 BuiltinType::Standard(ref ty) => ty.demangle(ctx, scope),
4098 BuiltinType::Extension(ref name) => name.demangle(ctx, scope),
4099 }
4100 }
4101 }
4102
4103 impl<'a> GetLeafName<'a> for BuiltinType {
get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>>4104 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
4105 None
4106 }
4107 }
4108
4109 /// A built-in type with CV-qualifiers.
4110 ///
4111 /// Like unqualified built-in types, CV-qualified built-in types do not go into
4112 /// the substitutions table.
4113 #[derive(Clone, Debug, PartialEq, Eq)]
4114 pub struct QualifiedBuiltin(CvQualifiers, BuiltinType);
4115
4116 impl<'subs, W> Demangle<'subs, W> for QualifiedBuiltin
4117 where
4118 W: 'subs + DemangleWrite,
4119 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4120 fn demangle<'prev, 'ctx>(
4121 &'subs self,
4122 ctx: &'ctx mut DemangleContext<'subs, W>,
4123 scope: Option<ArgScopeStack<'prev, 'subs>>,
4124 ) -> fmt::Result {
4125 let ctx = try_begin_demangle!(self, ctx, scope);
4126
4127 ctx.push_inner(&self.0);
4128 self.1.demangle(ctx, scope)?;
4129 if ctx.pop_inner_if(&self.0) {
4130 self.0.demangle_as_inner(ctx, scope)?;
4131 }
4132 Ok(())
4133 }
4134 }
4135
4136 impl<'a> GetLeafName<'a> for QualifiedBuiltin {
get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>>4137 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
4138 None
4139 }
4140 }
4141
4142 /// The `<function-type>` production.
4143 ///
4144 /// ```text
4145 /// <function-type> ::= [<CV-qualifiers>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
4146 /// ```
4147 #[derive(Clone, Debug, PartialEq, Eq)]
4148 pub struct FunctionType {
4149 cv_qualifiers: CvQualifiers,
4150 transaction_safe: bool,
4151 extern_c: bool,
4152 bare: BareFunctionType,
4153 ref_qualifier: Option<RefQualifier>,
4154 }
4155
4156 impl Parse for FunctionType {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(FunctionType, IndexStr<'b>)>4157 fn parse<'a, 'b>(
4158 ctx: &'a ParseContext,
4159 subs: &'a mut SubstitutionTable,
4160 input: IndexStr<'b>,
4161 ) -> Result<(FunctionType, IndexStr<'b>)> {
4162 try_begin_parse!("FunctionType", ctx, input);
4163
4164 let (cv_qualifiers, tail) =
4165 if let Ok((cv_qualifiers, tail)) = CvQualifiers::parse(ctx, subs, input) {
4166 (cv_qualifiers, tail)
4167 } else {
4168 (Default::default(), input)
4169 };
4170
4171 let (transaction_safe, tail) = if let Ok(tail) = consume(b"Dx", tail) {
4172 (true, tail)
4173 } else {
4174 (false, tail)
4175 };
4176
4177 let tail = consume(b"F", tail)?;
4178
4179 let (extern_c, tail) = if let Ok(tail) = consume(b"Y", tail) {
4180 (true, tail)
4181 } else {
4182 (false, tail)
4183 };
4184
4185 let (bare, tail) = BareFunctionType::parse(ctx, subs, tail)?;
4186
4187 let (ref_qualifier, tail) =
4188 if let Ok((ref_qualifier, tail)) = RefQualifier::parse(ctx, subs, tail) {
4189 (Some(ref_qualifier), tail)
4190 } else {
4191 (None, tail)
4192 };
4193
4194 let tail = consume(b"E", tail)?;
4195
4196 let func_ty = FunctionType {
4197 cv_qualifiers: cv_qualifiers,
4198 transaction_safe: transaction_safe,
4199 extern_c: extern_c,
4200 bare: bare,
4201 ref_qualifier: ref_qualifier,
4202 };
4203 Ok((func_ty, tail))
4204 }
4205 }
4206
4207 impl<'subs, W> Demangle<'subs, W> for FunctionType
4208 where
4209 W: 'subs + DemangleWrite,
4210 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4211 fn demangle<'prev, 'ctx>(
4212 &'subs self,
4213 ctx: &'ctx mut DemangleContext<'subs, W>,
4214 scope: Option<ArgScopeStack<'prev, 'subs>>,
4215 ) -> fmt::Result {
4216 let ctx = try_begin_demangle!(self, ctx, scope);
4217
4218 ctx.push_inner(self);
4219 self.bare.demangle(ctx, scope)?;
4220 if ctx.pop_inner_if(self) {
4221 self.demangle_as_inner(ctx, scope)?;
4222 }
4223 Ok(())
4224 }
4225 }
4226
4227 impl<'subs, W> DemangleAsInner<'subs, W> for FunctionType
4228 where
4229 W: 'subs + DemangleWrite,
4230 {
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4231 fn demangle_as_inner<'prev, 'ctx>(
4232 &'subs self,
4233 ctx: &'ctx mut DemangleContext<'subs, W>,
4234 scope: Option<ArgScopeStack<'prev, 'subs>>,
4235 ) -> fmt::Result {
4236 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4237
4238 if !self.cv_qualifiers.is_empty() {
4239 self.cv_qualifiers.demangle(ctx, scope)?;
4240 }
4241
4242 if let Some(ref rq) = self.ref_qualifier {
4243 // Print out a space before printing "&" or "&&"
4244 ctx.ensure_space()?;
4245 rq.demangle(ctx, scope)?;
4246 }
4247
4248 Ok(())
4249 }
4250
downcast_to_function_type(&self) -> Option<&FunctionType>4251 fn downcast_to_function_type(&self) -> Option<&FunctionType> {
4252 Some(self)
4253 }
4254 }
4255
4256 /// The `<bare-function-type>` production.
4257 ///
4258 /// ```text
4259 /// <bare-function-type> ::= <signature type>+
4260 /// # types are possible return type, then parameter types
4261 /// ```
4262 #[derive(Clone, Debug, PartialEq, Eq)]
4263 pub struct BareFunctionType(Vec<TypeHandle>);
4264
4265 impl BareFunctionType {
ret(&self) -> &TypeHandle4266 fn ret(&self) -> &TypeHandle {
4267 &self.0[0]
4268 }
4269
args(&self) -> &FunctionArgListAndReturnType4270 fn args(&self) -> &FunctionArgListAndReturnType {
4271 FunctionArgListAndReturnType::new(&self.0)
4272 }
4273 }
4274
4275 impl Parse for BareFunctionType {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(BareFunctionType, IndexStr<'b>)>4276 fn parse<'a, 'b>(
4277 ctx: &'a ParseContext,
4278 subs: &'a mut SubstitutionTable,
4279 input: IndexStr<'b>,
4280 ) -> Result<(BareFunctionType, IndexStr<'b>)> {
4281 try_begin_parse!("BareFunctionType", ctx, input);
4282
4283 let (types, tail) = one_or_more::<TypeHandle>(ctx, subs, input)?;
4284 Ok((BareFunctionType(types), tail))
4285 }
4286 }
4287
4288 impl<'subs, W> Demangle<'subs, W> for BareFunctionType
4289 where
4290 W: 'subs + DemangleWrite,
4291 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4292 fn demangle<'prev, 'ctx>(
4293 &'subs self,
4294 ctx: &'ctx mut DemangleContext<'subs, W>,
4295 scope: Option<ArgScopeStack<'prev, 'subs>>,
4296 ) -> fmt::Result {
4297 let ctx = try_begin_demangle!(self, ctx, scope);
4298
4299 ctx.push_inner(self);
4300
4301 self.ret().demangle(ctx, scope)?;
4302
4303 if ctx.pop_inner_if(self) {
4304 ctx.ensure_space()?;
4305 self.demangle_as_inner(ctx, scope)?;
4306 }
4307
4308 Ok(())
4309 }
4310 }
4311
4312 impl<'subs, W> DemangleAsInner<'subs, W> for BareFunctionType
4313 where
4314 W: 'subs + DemangleWrite,
4315 {
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4316 fn demangle_as_inner<'prev, 'ctx>(
4317 &'subs self,
4318 ctx: &'ctx mut DemangleContext<'subs, W>,
4319 scope: Option<ArgScopeStack<'prev, 'subs>>,
4320 ) -> fmt::Result {
4321 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4322 self.args().demangle_as_inner(ctx, scope)?;
4323 Ok(())
4324 }
4325 }
4326
4327 /// The `<decltype>` production.
4328 ///
4329 /// ```text
4330 /// <decltype> ::= Dt <expression> E
4331 /// ::= DT <expression> E
4332 /// ```
4333 #[derive(Clone, Debug, PartialEq, Eq)]
4334 pub enum Decltype {
4335 /// A `decltype` of an id-expression or class member access (C++0x).
4336 IdExpression(Expression),
4337
4338 /// A `decltype` of an expression (C++0x).
4339 Expression(Expression),
4340 }
4341
4342 impl Parse for Decltype {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Decltype, IndexStr<'b>)>4343 fn parse<'a, 'b>(
4344 ctx: &'a ParseContext,
4345 subs: &'a mut SubstitutionTable,
4346 input: IndexStr<'b>,
4347 ) -> Result<(Decltype, IndexStr<'b>)> {
4348 try_begin_parse!("Decltype", ctx, input);
4349
4350 let tail = consume(b"D", input)?;
4351
4352 if let Ok(tail) = consume(b"t", tail) {
4353 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
4354 let tail = consume(b"E", tail)?;
4355 return Ok((Decltype::IdExpression(expr), tail));
4356 }
4357
4358 let tail = consume(b"T", tail)?;
4359 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
4360 let tail = consume(b"E", tail)?;
4361 Ok((Decltype::Expression(expr), tail))
4362 }
4363 }
4364
4365 impl<'subs, W> Demangle<'subs, W> for Decltype
4366 where
4367 W: 'subs + DemangleWrite,
4368 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4369 fn demangle<'prev, 'ctx>(
4370 &'subs self,
4371 ctx: &'ctx mut DemangleContext<'subs, W>,
4372 scope: Option<ArgScopeStack<'prev, 'subs>>,
4373 ) -> fmt::Result {
4374 let ctx = try_begin_demangle!(self, ctx, scope);
4375
4376 ctx.push_demangle_node(DemangleNodeType::TemplateParam);
4377 let ret = match *self {
4378 Decltype::Expression(ref expr) | Decltype::IdExpression(ref expr) => {
4379 write!(ctx, "decltype (")?;
4380 expr.demangle(ctx, scope)?;
4381 write!(ctx, ")")?;
4382 Ok(())
4383 }
4384 };
4385 ctx.pop_demangle_node();
4386 ret
4387 }
4388 }
4389
4390 /// The `<class-enum-type>` production.
4391 ///
4392 /// ```text
4393 /// <class-enum-type> ::= <name>
4394 /// ::= Ts <name>
4395 /// ::= Tu <name>
4396 /// ::= Te <name>
4397 /// ```
4398 #[derive(Clone, Debug, PartialEq, Eq)]
4399 pub enum ClassEnumType {
4400 /// A non-dependent type name, dependent type name, or dependent
4401 /// typename-specifier.
4402 Named(Name),
4403
4404 /// A dependent elaborated type specifier using 'struct' or 'class'.
4405 ElaboratedStruct(Name),
4406
4407 /// A dependent elaborated type specifier using 'union'.
4408 ElaboratedUnion(Name),
4409
4410 /// A dependent elaborated type specifier using 'enum'.
4411 ElaboratedEnum(Name),
4412 }
4413
4414 impl Parse for ClassEnumType {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(ClassEnumType, IndexStr<'b>)>4415 fn parse<'a, 'b>(
4416 ctx: &'a ParseContext,
4417 subs: &'a mut SubstitutionTable,
4418 input: IndexStr<'b>,
4419 ) -> Result<(ClassEnumType, IndexStr<'b>)> {
4420 try_begin_parse!("ClassEnumType", ctx, input);
4421
4422 if let Ok((name, tail)) = Name::parse(ctx, subs, input) {
4423 return Ok((ClassEnumType::Named(name), tail));
4424 }
4425
4426 let tail = consume(b"T", input)?;
4427
4428 if let Ok(tail) = consume(b"s", tail) {
4429 let (name, tail) = Name::parse(ctx, subs, tail)?;
4430 return Ok((ClassEnumType::ElaboratedStruct(name), tail));
4431 }
4432
4433 if let Ok(tail) = consume(b"u", tail) {
4434 let (name, tail) = Name::parse(ctx, subs, tail)?;
4435 return Ok((ClassEnumType::ElaboratedUnion(name), tail));
4436 }
4437
4438 let tail = consume(b"e", tail)?;
4439 let (name, tail) = Name::parse(ctx, subs, tail)?;
4440 Ok((ClassEnumType::ElaboratedEnum(name), tail))
4441 }
4442 }
4443
4444 impl<'subs, W> Demangle<'subs, W> for ClassEnumType
4445 where
4446 W: 'subs + DemangleWrite,
4447 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4448 fn demangle<'prev, 'ctx>(
4449 &'subs self,
4450 ctx: &'ctx mut DemangleContext<'subs, W>,
4451 scope: Option<ArgScopeStack<'prev, 'subs>>,
4452 ) -> fmt::Result {
4453 let ctx = try_begin_demangle!(self, ctx, scope);
4454
4455 match *self {
4456 ClassEnumType::Named(ref name) => name.demangle(ctx, scope),
4457 ClassEnumType::ElaboratedStruct(ref name) => {
4458 write!(ctx, "class ")?;
4459 name.demangle(ctx, scope)
4460 }
4461 ClassEnumType::ElaboratedUnion(ref name) => {
4462 write!(ctx, "union ")?;
4463 name.demangle(ctx, scope)
4464 }
4465 ClassEnumType::ElaboratedEnum(ref name) => {
4466 write!(ctx, "enum ")?;
4467 name.demangle(ctx, scope)
4468 }
4469 }
4470 }
4471 }
4472
4473 impl<'a> GetLeafName<'a> for ClassEnumType {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>4474 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
4475 match *self {
4476 ClassEnumType::Named(ref name)
4477 | ClassEnumType::ElaboratedStruct(ref name)
4478 | ClassEnumType::ElaboratedUnion(ref name)
4479 | ClassEnumType::ElaboratedEnum(ref name) => name.get_leaf_name(subs),
4480 }
4481 }
4482 }
4483
4484 /// The `<unnamed-type-name>` production.
4485 ///
4486 /// ```text
4487 /// <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
4488 /// ::= <closure-type-name>
4489 /// ```
4490 ///
4491 /// TODO: parse the <closure-type-name> variant
4492 #[derive(Clone, Debug, PartialEq, Eq)]
4493 pub struct UnnamedTypeName(Option<usize>);
4494
4495 impl Parse for UnnamedTypeName {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(UnnamedTypeName, IndexStr<'b>)>4496 fn parse<'a, 'b>(
4497 ctx: &'a ParseContext,
4498 _subs: &'a mut SubstitutionTable,
4499 input: IndexStr<'b>,
4500 ) -> Result<(UnnamedTypeName, IndexStr<'b>)> {
4501 try_begin_parse!("UnnamedTypeName", ctx, input);
4502
4503 let input = consume(b"Ut", input)?;
4504 let (number, input) = match parse_number(10, false, input) {
4505 Ok((number, input)) => (Some(number as _), input),
4506 Err(_) => (None, input),
4507 };
4508 let input = consume(b"_", input)?;
4509 Ok((UnnamedTypeName(number), input))
4510 }
4511 }
4512
4513 impl UnnamedTypeName {
4514 #[inline]
starts_with(byte: u8) -> bool4515 fn starts_with(byte: u8) -> bool {
4516 byte == b'U'
4517 }
4518 }
4519
4520 impl<'subs, W> Demangle<'subs, W> for UnnamedTypeName
4521 where
4522 W: 'subs + DemangleWrite,
4523 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4524 fn demangle<'prev, 'ctx>(
4525 &'subs self,
4526 ctx: &'ctx mut DemangleContext<'subs, W>,
4527 scope: Option<ArgScopeStack<'prev, 'subs>>,
4528 ) -> fmt::Result {
4529 let ctx = try_begin_demangle!(self, ctx, scope);
4530
4531 write!(ctx, "{{unnamed type#{}}}", self.0.map_or(1, |n| n + 1))?;
4532 Ok(())
4533 }
4534 }
4535
4536 impl<'subs, W> DemangleAsLeaf<'subs, W> for UnnamedTypeName
4537 where
4538 W: 'subs + DemangleWrite,
4539 {
demangle_as_leaf<'me, 'ctx>( &'me self, ctx: &'ctx mut DemangleContext<'subs, W>, ) -> fmt::Result4540 fn demangle_as_leaf<'me, 'ctx>(
4541 &'me self,
4542 ctx: &'ctx mut DemangleContext<'subs, W>,
4543 ) -> fmt::Result {
4544 let ctx = try_begin_demangle!(self, ctx, None);
4545 if let Some(source_name) = ctx.source_name {
4546 write!(ctx, "{}", source_name)?;
4547 } else {
4548 write!(ctx, "{{unnamed type#{}}}", self.0.map_or(1, |n| n + 1))?;
4549 }
4550 Ok(())
4551 }
4552 }
4553
4554 impl<'subs> ArgScope<'subs, 'subs> for UnnamedTypeName {
leaf_name(&'subs self) -> Result<LeafName<'subs>>4555 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
4556 Ok(LeafName::UnnamedType(self))
4557 }
4558
get_template_arg( &'subs self, _: usize, ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)>4559 fn get_template_arg(
4560 &'subs self,
4561 _: usize,
4562 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
4563 Err(error::Error::BadTemplateArgReference)
4564 }
4565
get_function_arg(&'subs self, _: usize) -> Result<&'subs Type>4566 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
4567 Err(error::Error::BadFunctionArgReference)
4568 }
4569 }
4570
4571 /// The `<array-type>` production.
4572 ///
4573 /// ```text
4574 /// <array-type> ::= A <positive dimension number> _ <element type>
4575 /// ::= A [<dimension expression>] _ <element type>
4576 /// ```
4577 #[derive(Clone, Debug, PartialEq, Eq)]
4578 pub enum ArrayType {
4579 /// An array with a number-literal dimension.
4580 DimensionNumber(usize, TypeHandle),
4581
4582 /// An array with an expression for its dimension.
4583 DimensionExpression(Expression, TypeHandle),
4584
4585 /// An array with no dimension.
4586 NoDimension(TypeHandle),
4587 }
4588
4589 impl Parse for ArrayType {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(ArrayType, IndexStr<'b>)>4590 fn parse<'a, 'b>(
4591 ctx: &'a ParseContext,
4592 subs: &'a mut SubstitutionTable,
4593 input: IndexStr<'b>,
4594 ) -> Result<(ArrayType, IndexStr<'b>)> {
4595 try_begin_parse!("ArrayType", ctx, input);
4596
4597 let tail = consume(b"A", input)?;
4598
4599 if let Ok((num, tail)) = parse_number(10, false, tail) {
4600 debug_assert!(num >= 0);
4601 let tail = consume(b"_", tail)?;
4602 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4603 return Ok((ArrayType::DimensionNumber(num as _, ty), tail));
4604 }
4605
4606 if let Ok((expr, tail)) = Expression::parse(ctx, subs, tail) {
4607 let tail = consume(b"_", tail)?;
4608 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4609 return Ok((ArrayType::DimensionExpression(expr, ty), tail));
4610 }
4611
4612 let tail = consume(b"_", tail)?;
4613 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4614 Ok((ArrayType::NoDimension(ty), tail))
4615 }
4616 }
4617
4618 impl<'subs, W> Demangle<'subs, W> for ArrayType
4619 where
4620 W: 'subs + DemangleWrite,
4621 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4622 fn demangle<'prev, 'ctx>(
4623 &'subs self,
4624 ctx: &'ctx mut DemangleContext<'subs, W>,
4625 scope: Option<ArgScopeStack<'prev, 'subs>>,
4626 ) -> fmt::Result {
4627 let ctx = try_begin_demangle!(self, ctx, scope);
4628
4629 ctx.push_inner(self);
4630
4631 match *self {
4632 ArrayType::DimensionNumber(_, ref ty)
4633 | ArrayType::DimensionExpression(_, ref ty)
4634 | ArrayType::NoDimension(ref ty) => {
4635 ty.demangle(ctx, scope)?;
4636 }
4637 }
4638
4639 if ctx.pop_inner_if(self) {
4640 self.demangle_as_inner(ctx, scope)?;
4641 }
4642
4643 Ok(())
4644 }
4645 }
4646
4647 impl<'subs, W> DemangleAsInner<'subs, W> for ArrayType
4648 where
4649 W: 'subs + DemangleWrite,
4650 {
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4651 fn demangle_as_inner<'prev, 'ctx>(
4652 &'subs self,
4653 ctx: &'ctx mut DemangleContext<'subs, W>,
4654 scope: Option<ArgScopeStack<'prev, 'subs>>,
4655 ) -> fmt::Result {
4656 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4657
4658 // Whether we should add a final space before the dimensions.
4659 let mut needs_space = true;
4660
4661 while let Some(inner) = ctx.pop_inner() {
4662 // We need to add parentheses around array inner types, unless they
4663 // are also (potentially qualified) arrays themselves, in which case
4664 // we format them as multi-dimensional arrays.
4665 let inner_is_array = match inner.downcast_to_type() {
4666 Some(&Type::Qualified(_, ref ty)) => ctx.subs.get_type(ty).map_or(false, |ty| {
4667 DemangleAsInner::<W>::downcast_to_array_type(ty).is_some()
4668 }),
4669 _ => {
4670 if inner.downcast_to_array_type().is_some() {
4671 needs_space = false;
4672 true
4673 } else {
4674 false
4675 }
4676 }
4677 };
4678
4679 if inner_is_array {
4680 inner.demangle_as_inner(ctx, scope)?;
4681 } else {
4682 ctx.ensure_space()?;
4683
4684 // CvQualifiers should have the parentheses printed after, not before
4685 if inner.is_qualified() {
4686 inner.demangle_as_inner(ctx, scope)?;
4687 ctx.ensure_space()?;
4688 write!(ctx, "(")?;
4689 } else {
4690 write!(ctx, "(")?;
4691 inner.demangle_as_inner(ctx, scope)?;
4692 }
4693
4694 ctx.demangle_inners(scope)?;
4695 write!(ctx, ")")?;
4696 }
4697 }
4698
4699 if needs_space {
4700 ctx.ensure_space()?;
4701 }
4702
4703 match *self {
4704 ArrayType::DimensionNumber(n, _) => {
4705 write!(ctx, "[{}]", n)?;
4706 }
4707 ArrayType::DimensionExpression(ref expr, _) => {
4708 write!(ctx, "[")?;
4709 expr.demangle(ctx, scope)?;
4710 write!(ctx, "]")?;
4711 }
4712 ArrayType::NoDimension(_) => {
4713 write!(ctx, "[]")?;
4714 }
4715 }
4716
4717 Ok(())
4718 }
4719
downcast_to_array_type(&self) -> Option<&ArrayType>4720 fn downcast_to_array_type(&self) -> Option<&ArrayType> {
4721 Some(self)
4722 }
4723 }
4724
4725 /// The `<vector-type>` production.
4726 ///
4727 /// ```text
4728 /// <vector-type> ::= Dv <number> _ <type>
4729 /// ::= Dv _ <expression> _ <type>
4730 /// ```
4731 #[derive(Clone, Debug, PartialEq, Eq)]
4732 pub enum VectorType {
4733 /// An vector with a number-literal dimension.
4734 DimensionNumber(usize, TypeHandle),
4735
4736 /// An vector with an expression for its dimension.
4737 DimensionExpression(Expression, TypeHandle),
4738 }
4739
4740 impl Parse for VectorType {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(VectorType, IndexStr<'b>)>4741 fn parse<'a, 'b>(
4742 ctx: &'a ParseContext,
4743 subs: &'a mut SubstitutionTable,
4744 input: IndexStr<'b>,
4745 ) -> Result<(VectorType, IndexStr<'b>)> {
4746 try_begin_parse!("VectorType", ctx, input);
4747
4748 let tail = consume(b"Dv", input)?;
4749
4750 if let Ok((num, tail)) = parse_number(10, false, tail) {
4751 debug_assert!(num >= 0);
4752 let tail = consume(b"_", tail)?;
4753 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4754 return Ok((VectorType::DimensionNumber(num as _, ty), tail));
4755 }
4756
4757 let tail = consume(b"_", tail)?;
4758 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
4759 let tail = consume(b"_", tail)?;
4760 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4761 Ok((VectorType::DimensionExpression(expr, ty), tail))
4762 }
4763 }
4764
4765 impl<'subs, W> Demangle<'subs, W> for VectorType
4766 where
4767 W: 'subs + DemangleWrite,
4768 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4769 fn demangle<'prev, 'ctx>(
4770 &'subs self,
4771 ctx: &'ctx mut DemangleContext<'subs, W>,
4772 scope: Option<ArgScopeStack<'prev, 'subs>>,
4773 ) -> fmt::Result {
4774 let ctx = try_begin_demangle!(self, ctx, scope);
4775
4776 ctx.push_inner(self);
4777
4778 match *self {
4779 VectorType::DimensionNumber(_, ref ty) | VectorType::DimensionExpression(_, ref ty) => {
4780 ty.demangle(ctx, scope)?;
4781 }
4782 }
4783
4784 if ctx.pop_inner_if(self) {
4785 self.demangle_as_inner(ctx, scope)?;
4786 }
4787
4788 Ok(())
4789 }
4790 }
4791
4792 impl<'subs, W> DemangleAsInner<'subs, W> for VectorType
4793 where
4794 W: 'subs + DemangleWrite,
4795 {
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4796 fn demangle_as_inner<'prev, 'ctx>(
4797 &'subs self,
4798 ctx: &'ctx mut DemangleContext<'subs, W>,
4799 scope: Option<ArgScopeStack<'prev, 'subs>>,
4800 ) -> fmt::Result {
4801 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4802
4803 match *self {
4804 VectorType::DimensionNumber(n, _) => {
4805 write!(ctx, " __vector({})", n)?;
4806 }
4807 VectorType::DimensionExpression(ref expr, _) => {
4808 write!(ctx, " __vector(")?;
4809 expr.demangle(ctx, scope)?;
4810 write!(ctx, ")")?;
4811 }
4812 }
4813
4814 Ok(())
4815 }
4816 }
4817
4818 /// The `<pointer-to-member-type>` production.
4819 ///
4820 /// ```text
4821 /// <pointer-to-member-type> ::= M <class type> <member type>
4822 /// ```
4823 #[derive(Clone, Debug, PartialEq, Eq)]
4824 pub struct PointerToMemberType(TypeHandle, TypeHandle);
4825
4826 impl Parse for PointerToMemberType {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(PointerToMemberType, IndexStr<'b>)>4827 fn parse<'a, 'b>(
4828 ctx: &'a ParseContext,
4829 subs: &'a mut SubstitutionTable,
4830 input: IndexStr<'b>,
4831 ) -> Result<(PointerToMemberType, IndexStr<'b>)> {
4832 try_begin_parse!("PointerToMemberType", ctx, input);
4833
4834 let tail = consume(b"M", input)?;
4835 let (ty1, tail) = TypeHandle::parse(ctx, subs, tail)?;
4836 let (ty2, tail) = TypeHandle::parse(ctx, subs, tail)?;
4837 Ok((PointerToMemberType(ty1, ty2), tail))
4838 }
4839 }
4840
4841 impl<'subs, W> Demangle<'subs, W> for PointerToMemberType
4842 where
4843 W: 'subs + DemangleWrite,
4844 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4845 fn demangle<'prev, 'ctx>(
4846 &'subs self,
4847 ctx: &'ctx mut DemangleContext<'subs, W>,
4848 scope: Option<ArgScopeStack<'prev, 'subs>>,
4849 ) -> fmt::Result {
4850 let ctx = try_begin_demangle!(self, ctx, scope);
4851
4852 ctx.push_inner(self);
4853 self.1.demangle(ctx, scope)?;
4854 if ctx.pop_inner_if(self) {
4855 self.demangle_as_inner(ctx, scope)?;
4856 }
4857 Ok(())
4858 }
4859 }
4860
4861 impl<'subs, W> DemangleAsInner<'subs, W> for PointerToMemberType
4862 where
4863 W: 'subs + DemangleWrite,
4864 {
demangle_as_inner<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4865 fn demangle_as_inner<'prev, 'ctx>(
4866 &'subs self,
4867 ctx: &'ctx mut DemangleContext<'subs, W>,
4868 scope: Option<ArgScopeStack<'prev, 'subs>>,
4869 ) -> fmt::Result {
4870 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4871
4872 if ctx.last_char_written != Some('(') {
4873 ctx.ensure_space()?;
4874 }
4875
4876 self.0.demangle(ctx, scope)?;
4877 write!(ctx, "::*")?;
4878 Ok(())
4879 }
4880
downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType>4881 fn downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType> {
4882 Some(self)
4883 }
4884 }
4885
4886 /// The `<template-param>` production.
4887 ///
4888 /// ```text
4889 /// <template-param> ::= T_ # first template parameter
4890 /// ::= T <parameter-2 non-negative number> _
4891 /// ```
4892 #[derive(Clone, Debug, PartialEq, Eq)]
4893 pub struct TemplateParam(usize);
4894
4895 impl Parse for TemplateParam {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(TemplateParam, IndexStr<'b>)>4896 fn parse<'a, 'b>(
4897 ctx: &'a ParseContext,
4898 _subs: &'a mut SubstitutionTable,
4899 input: IndexStr<'b>,
4900 ) -> Result<(TemplateParam, IndexStr<'b>)> {
4901 try_begin_parse!("TemplateParam", ctx, input);
4902
4903 let input = consume(b"T", input)?;
4904 let (number, input) = match parse_number(10, false, input) {
4905 Ok((number, input)) => ((number + 1) as _, input),
4906 Err(_) => (0, input),
4907 };
4908 let input = consume(b"_", input)?;
4909 Ok((TemplateParam(number), input))
4910 }
4911 }
4912
4913 impl<'subs, W> Demangle<'subs, W> for TemplateParam
4914 where
4915 W: 'subs + DemangleWrite,
4916 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result4917 fn demangle<'prev, 'ctx>(
4918 &'subs self,
4919 ctx: &'ctx mut DemangleContext<'subs, W>,
4920 scope: Option<ArgScopeStack<'prev, 'subs>>,
4921 ) -> fmt::Result {
4922 let ctx = try_begin_demangle!(self, ctx, scope);
4923
4924 ctx.push_demangle_node(DemangleNodeType::TemplateParam);
4925 let ret = if ctx.is_lambda_arg {
4926 // To match libiberty, template references are converted to `auto`.
4927 write!(ctx, "auto:{}", self.0 + 1)
4928 } else {
4929 let arg = self.resolve(scope)?;
4930 arg.demangle(ctx, scope)
4931 };
4932 ctx.pop_demangle_node();
4933 ret
4934 }
4935 }
4936
4937 impl TemplateParam {
resolve<'subs, 'prev>( &'subs self, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> ::std::result::Result<&'subs TemplateArg, fmt::Error>4938 fn resolve<'subs, 'prev>(
4939 &'subs self,
4940 scope: Option<ArgScopeStack<'prev, 'subs>>,
4941 ) -> ::std::result::Result<&'subs TemplateArg, fmt::Error> {
4942 scope
4943 .get_template_arg(self.0)
4944 .map_err(|e| {
4945 log!("Error obtaining template argument: {}", e);
4946 fmt::Error
4947 })
4948 .map(|v| v.0)
4949 }
4950 }
4951
4952 impl<'a> Hash for &'a TemplateParam {
hash<H>(&self, state: &mut H) where H: Hasher,4953 fn hash<H>(&self, state: &mut H)
4954 where
4955 H: Hasher,
4956 {
4957 let self_ref: &TemplateParam = *self;
4958 let self_ptr = self_ref as *const TemplateParam;
4959 self_ptr.hash(state);
4960 }
4961 }
4962
4963 /// The `<template-template-param>` production.
4964 ///
4965 /// ```text
4966 /// <template-template-param> ::= <template-param>
4967 /// ::= <substitution>
4968 /// ```
4969 #[derive(Clone, Debug, PartialEq, Eq)]
4970 pub struct TemplateTemplateParam(TemplateParam);
4971
4972 define_handle! {
4973 /// A reference to a parsed `TemplateTemplateParam`.
4974 pub enum TemplateTemplateParamHandle
4975 }
4976
4977 impl Parse for TemplateTemplateParamHandle {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(TemplateTemplateParamHandle, IndexStr<'b>)>4978 fn parse<'a, 'b>(
4979 ctx: &'a ParseContext,
4980 subs: &'a mut SubstitutionTable,
4981 input: IndexStr<'b>,
4982 ) -> Result<(TemplateTemplateParamHandle, IndexStr<'b>)> {
4983 try_begin_parse!("TemplateTemplateParamHandle", ctx, input);
4984
4985 if let Ok((sub, tail)) = Substitution::parse(ctx, subs, input) {
4986 match sub {
4987 Substitution::WellKnown(component) => {
4988 return Ok((TemplateTemplateParamHandle::WellKnown(component), tail));
4989 }
4990 Substitution::BackReference(idx) => {
4991 // TODO: should this check if the thing at idx is a
4992 // template-template-param? There could otherwise be ambiguity
4993 // with <type>'s <substitution> form...
4994 return Ok((TemplateTemplateParamHandle::BackReference(idx), tail));
4995 }
4996 }
4997 }
4998
4999 let (param, tail) = TemplateParam::parse(ctx, subs, input)?;
5000 let ttp = TemplateTemplateParam(param);
5001 let ttp = Substitutable::TemplateTemplateParam(ttp);
5002 let idx = subs.insert(ttp);
5003 let handle = TemplateTemplateParamHandle::BackReference(idx);
5004 Ok((handle, tail))
5005 }
5006 }
5007
5008 impl<'subs, W> Demangle<'subs, W> for TemplateTemplateParam
5009 where
5010 W: 'subs + DemangleWrite,
5011 {
5012 #[inline]
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result5013 fn demangle<'prev, 'ctx>(
5014 &'subs self,
5015 ctx: &'ctx mut DemangleContext<'subs, W>,
5016 scope: Option<ArgScopeStack<'prev, 'subs>>,
5017 ) -> fmt::Result {
5018 let ctx = try_begin_demangle!(self, ctx, scope);
5019
5020 self.0.demangle(ctx, scope)
5021 }
5022 }
5023
5024 /// The <function-param> production.
5025 ///
5026 /// ```text
5027 /// <function-param> ::= fp <top-level CV-qualifiers> _
5028 /// # L == 0, first parameter
5029 /// ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _
5030 /// # L == 0, second and later parameters
5031 /// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _
5032 /// # L > 0, first parameter
5033 /// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> <parameter-2 non-negative number> _
5034 /// # L > 0, second and later parameters
5035 /// ```
5036 #[derive(Clone, Debug, PartialEq, Eq)]
5037 pub struct FunctionParam(usize, CvQualifiers, Option<usize>);
5038
5039 impl Parse for FunctionParam {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(FunctionParam, IndexStr<'b>)>5040 fn parse<'a, 'b>(
5041 ctx: &'a ParseContext,
5042 subs: &'a mut SubstitutionTable,
5043 input: IndexStr<'b>,
5044 ) -> Result<(FunctionParam, IndexStr<'b>)> {
5045 try_begin_parse!("FunctionParam", ctx, input);
5046
5047 let tail = consume(b"f", input)?;
5048 if tail.is_empty() {
5049 return Err(error::Error::UnexpectedEnd);
5050 }
5051
5052 let (scope, tail) = if let Ok(tail) = consume(b"L", tail) {
5053 parse_number(10, false, tail)?
5054 } else {
5055 (0, tail)
5056 };
5057
5058 let tail = consume(b"p", tail)?;
5059
5060 let (qualifiers, tail) = CvQualifiers::parse(ctx, subs, tail)?;
5061
5062 let (param, tail) = if tail.peek() == Some(b'T') {
5063 (None, consume(b"T", tail)?)
5064 } else if let Ok((num, tail)) = parse_number(10, false, tail) {
5065 (Some(num as usize + 1), consume(b"_", tail)?)
5066 } else {
5067 (Some(0), consume(b"_", tail)?)
5068 };
5069
5070 Ok((FunctionParam(scope as _, qualifiers, param), tail))
5071 }
5072 }
5073
5074 impl<'subs, W> Demangle<'subs, W> for FunctionParam
5075 where
5076 W: 'subs + DemangleWrite,
5077 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result5078 fn demangle<'prev, 'ctx>(
5079 &'subs self,
5080 ctx: &'ctx mut DemangleContext<'subs, W>,
5081 scope: Option<ArgScopeStack<'prev, 'subs>>,
5082 ) -> fmt::Result {
5083 let ctx = try_begin_demangle!(self, ctx, scope);
5084
5085 match self.2 {
5086 None => write!(ctx, "this"),
5087 Some(i) => write!(ctx, "{{parm#{}}}", i + 1),
5088 }
5089 }
5090 }
5091
5092 /// The `<template-args>` production.
5093 ///
5094 /// ```text
5095 /// <template-args> ::= I <template-arg>+ E
5096 /// ```
5097 #[derive(Clone, Debug, PartialEq, Eq)]
5098 pub struct TemplateArgs(Vec<TemplateArg>);
5099
5100 impl Parse for TemplateArgs {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(TemplateArgs, IndexStr<'b>)>5101 fn parse<'a, 'b>(
5102 ctx: &'a ParseContext,
5103 subs: &'a mut SubstitutionTable,
5104 input: IndexStr<'b>,
5105 ) -> Result<(TemplateArgs, IndexStr<'b>)> {
5106 try_begin_parse!("TemplateArgs", ctx, input);
5107
5108 let tail = consume(b"I", input)?;
5109
5110 let (args, tail) = one_or_more::<TemplateArg>(ctx, subs, tail)?;
5111 let tail = consume(b"E", tail)?;
5112 Ok((TemplateArgs(args), tail))
5113 }
5114 }
5115
5116 impl<'subs, W> Demangle<'subs, W> for TemplateArgs
5117 where
5118 W: 'subs + DemangleWrite,
5119 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, mut scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result5120 fn demangle<'prev, 'ctx>(
5121 &'subs self,
5122 ctx: &'ctx mut DemangleContext<'subs, W>,
5123 mut scope: Option<ArgScopeStack<'prev, 'subs>>,
5124 ) -> fmt::Result {
5125 let ctx = try_begin_demangle!(self, ctx, scope);
5126 inner_barrier!(ctx);
5127
5128 if ctx.last_char_written == Some('<') {
5129 write!(ctx, " ")?;
5130 }
5131 write!(ctx, "<")?;
5132 ctx.push_demangle_node(DemangleNodeType::TemplateArgs);
5133 let mut need_comma = false;
5134 for arg_index in 0..self.0.len() {
5135 if need_comma {
5136 write!(ctx, ", ")?;
5137 }
5138 if let Some(ref mut scope) = scope {
5139 scope.in_arg = Some((arg_index, self));
5140 }
5141 self.0[arg_index].demangle(ctx, scope)?;
5142 need_comma = true;
5143 }
5144
5145 // Ensure "> >" because old C++ sucks and libiberty (and its tests)
5146 // supports old C++.
5147 if ctx.last_char_written == Some('>') {
5148 write!(ctx, " ")?;
5149 }
5150 ctx.pop_demangle_node();
5151 write!(ctx, ">")?;
5152 Ok(())
5153 }
5154 }
5155
5156 impl<'subs> ArgScope<'subs, 'subs> for TemplateArgs {
leaf_name(&'subs self) -> Result<LeafName<'subs>>5157 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
5158 Err(error::Error::BadLeafNameReference)
5159 }
5160
get_template_arg( &'subs self, idx: usize, ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)>5161 fn get_template_arg(
5162 &'subs self,
5163 idx: usize,
5164 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
5165 self.0
5166 .get(idx)
5167 .ok_or(error::Error::BadTemplateArgReference)
5168 .map(|v| (v, self))
5169 }
5170
get_function_arg(&'subs self, _: usize) -> Result<&'subs Type>5171 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
5172 Err(error::Error::BadFunctionArgReference)
5173 }
5174 }
5175
5176 /// A <template-arg> production.
5177 ///
5178 /// ```text
5179 /// <template-arg> ::= <type> # type or template
5180 /// ::= X <expression> E # expression
5181 /// ::= <expr-primary> # simple expressions
5182 /// ::= J <template-arg>* E # argument pack
5183 /// ```
5184 #[derive(Clone, Debug, PartialEq, Eq)]
5185 pub enum TemplateArg {
5186 /// A type or template.
5187 Type(TypeHandle),
5188
5189 /// An expression.
5190 Expression(Expression),
5191
5192 /// A simple expression.
5193 SimpleExpression(ExprPrimary),
5194
5195 /// An argument pack.
5196 ArgPack(Vec<TemplateArg>),
5197 }
5198
5199 impl Parse for TemplateArg {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(TemplateArg, IndexStr<'b>)>5200 fn parse<'a, 'b>(
5201 ctx: &'a ParseContext,
5202 subs: &'a mut SubstitutionTable,
5203 input: IndexStr<'b>,
5204 ) -> Result<(TemplateArg, IndexStr<'b>)> {
5205 try_begin_parse!("TemplateArg", ctx, input);
5206
5207 if let Ok(tail) = consume(b"X", input) {
5208 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5209 let tail = consume(b"E", tail)?;
5210 return Ok((TemplateArg::Expression(expr), tail));
5211 }
5212
5213 if let Ok((expr, tail)) = ExprPrimary::parse(ctx, subs, input) {
5214 return Ok((TemplateArg::SimpleExpression(expr), tail));
5215 }
5216
5217 if let Ok((ty, tail)) = TypeHandle::parse(ctx, subs, input) {
5218 return Ok((TemplateArg::Type(ty), tail));
5219 }
5220
5221 let tail = if input.peek() == Some(b'J') {
5222 consume(b"J", input)?
5223 } else {
5224 consume(b"I", input)?
5225 };
5226
5227 let (args, tail) = if tail.peek() == Some(b'E') {
5228 (vec![], tail)
5229 } else {
5230 zero_or_more::<TemplateArg>(ctx, subs, tail)?
5231 };
5232 let tail = consume(b"E", tail)?;
5233 Ok((TemplateArg::ArgPack(args), tail))
5234 }
5235 }
5236
5237 impl<'subs, W> Demangle<'subs, W> for TemplateArg
5238 where
5239 W: 'subs + DemangleWrite,
5240 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result5241 fn demangle<'prev, 'ctx>(
5242 &'subs self,
5243 ctx: &'ctx mut DemangleContext<'subs, W>,
5244 scope: Option<ArgScopeStack<'prev, 'subs>>,
5245 ) -> fmt::Result {
5246 let ctx = try_begin_demangle!(self, ctx, scope);
5247
5248 match *self {
5249 TemplateArg::Type(ref ty) => ty.demangle(ctx, scope),
5250 TemplateArg::Expression(ref expr) => expr.demangle(ctx, scope),
5251 TemplateArg::SimpleExpression(ref expr) => expr.demangle(ctx, scope),
5252 TemplateArg::ArgPack(ref args) => {
5253 ctx.is_template_argument_pack = true;
5254 let mut need_comma = false;
5255 for arg in &args[..] {
5256 if need_comma {
5257 write!(ctx, ", ")?;
5258 }
5259 arg.demangle(ctx, scope)?;
5260 need_comma = true;
5261 }
5262 Ok(())
5263 }
5264 }
5265 }
5266 }
5267
5268 /// In libiberty, Member and DerefMember expressions have special handling.
5269 /// They parse an `UnqualifiedName` (not an `UnscopedName` as the cxxabi docs
5270 /// say) and optionally a `TemplateArgs` if it is present. We can't just parse
5271 /// a `Name` or an `UnscopedTemplateName` here because that allows other inputs
5272 /// that libiberty does not.
5273 #[derive(Clone, Debug, PartialEq, Eq)]
5274 pub struct MemberName(Name);
5275
5276 impl Parse for MemberName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(MemberName, IndexStr<'b>)>5277 fn parse<'a, 'b>(
5278 ctx: &'a ParseContext,
5279 subs: &'a mut SubstitutionTable,
5280 input: IndexStr<'b>,
5281 ) -> Result<(MemberName, IndexStr<'b>)> {
5282 try_begin_parse!("MemberName", ctx, input);
5283
5284 let (name, tail) = UnqualifiedName::parse(ctx, subs, input)?;
5285 let name = UnscopedName::Unqualified(name);
5286 if let Ok((template, tail)) = TemplateArgs::parse(ctx, subs, tail) {
5287 let name = UnscopedTemplateName(name);
5288 // In libiberty, these are unsubstitutable.
5289 let idx = subs.insert_non_substitution(Substitutable::UnscopedTemplateName(name));
5290 let handle = UnscopedTemplateNameHandle::NonSubstitution(NonSubstitution(idx));
5291 Ok((MemberName(Name::UnscopedTemplate(handle, template)), tail))
5292 } else {
5293 Ok((MemberName(Name::Unscoped(name)), tail))
5294 }
5295 }
5296 }
5297
5298 impl<'subs, W> Demangle<'subs, W> for MemberName
5299 where
5300 W: 'subs + DemangleWrite,
5301 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result5302 fn demangle<'prev, 'ctx>(
5303 &'subs self,
5304 ctx: &'ctx mut DemangleContext<'subs, W>,
5305 scope: Option<ArgScopeStack<'prev, 'subs>>,
5306 ) -> fmt::Result {
5307 let ctx = try_begin_demangle!(self, ctx, scope);
5308
5309 let needs_parens = self.0.get_template_args(ctx.subs).is_some();
5310 if needs_parens {
5311 write!(ctx, "(")?;
5312 }
5313
5314 self.0.demangle(ctx, scope)?;
5315
5316 if needs_parens {
5317 write!(ctx, ")")?;
5318 }
5319
5320 Ok(())
5321 }
5322 }
5323
5324 /// The `<expression>` production.
5325 ///
5326 /// ```text
5327 /// <expression> ::= <unary operator-name> <expression>
5328 /// ::= <binary operator-name> <expression> <expression>
5329 /// ::= <ternary operator-name> <expression> <expression> <expression>
5330 /// ::= pp_ <expression> # prefix ++
5331 /// ::= mm_ <expression> # prefix --
5332 /// ::= cl <expression>+ E # expression (expr-list), call
5333 /// ::= cv <type> <expression> # type (expression), conversion with one argument
5334 /// ::= cv <type> _ <expression>* E # type (expr-list), conversion with other than one argument
5335 /// ::= tl <type> <expression>* E # type {expr-list}, conversion with braced-init-list argument
5336 /// ::= il <expression> E # {expr-list}, braced-init-list in any other context
5337 /// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
5338 /// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
5339 /// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
5340 /// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
5341 /// ::= [gs] dl <expression> # delete expression
5342 /// ::= [gs] da <expression> # delete[] expression
5343 /// ::= dc <type> <expression> # dynamic_cast<type> (expression)
5344 /// ::= sc <type> <expression> # static_cast<type> (expression)
5345 /// ::= cc <type> <expression> # const_cast<type> (expression)
5346 /// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
5347 /// ::= ti <type> # typeid (type)
5348 /// ::= te <expression> # typeid (expression)
5349 /// ::= st <type> # sizeof (type)
5350 /// ::= sz <expression> # sizeof (expression)
5351 /// ::= at <type> # alignof (type)
5352 /// ::= az <expression> # alignof (expression)
5353 /// ::= nx <expression> # noexcept (expression)
5354 /// ::= <template-param>
5355 /// ::= <function-param>
5356 /// ::= dt <expression> <unresolved-name> # expr.name
5357 /// ::= pt <expression> <unresolved-name> # expr->name
5358 /// ::= ds <expression> <expression> # expr.*expr
5359 /// ::= sZ <template-param> # sizeof...(T), size of a template parameter pack
5360 /// ::= sZ <function-param> # sizeof...(parameter), size of a function parameter pack
5361 /// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
5362 /// ::= sp <expression> # expression..., pack expansion
5363 /// ::= tw <expression> # throw expression
5364 /// ::= tr # throw with no operand (rethrow)
5365 /// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
5366 /// # freestanding dependent name (e.g., T::x),
5367 /// # objectless nonstatic member reference
5368 /// ::= <expr-primary>
5369 /// ```
5370 #[derive(Clone, Debug, PartialEq, Eq)]
5371 pub enum Expression {
5372 /// A unary operator expression.
5373 Unary(OperatorName, Box<Expression>),
5374
5375 /// A binary operator expression.
5376 Binary(OperatorName, Box<Expression>, Box<Expression>),
5377
5378 /// A ternary operator expression.
5379 Ternary(
5380 OperatorName,
5381 Box<Expression>,
5382 Box<Expression>,
5383 Box<Expression>,
5384 ),
5385
5386 /// A prefix `++`.
5387 PrefixInc(Box<Expression>),
5388
5389 /// A prefix `--`.
5390 PrefixDec(Box<Expression>),
5391
5392 /// A call with functor and arguments.
5393 Call(Box<Expression>, Vec<Expression>),
5394
5395 /// A type conversion with one argument.
5396 ConversionOne(TypeHandle, Box<Expression>),
5397
5398 /// A type conversion with many arguments.
5399 ConversionMany(TypeHandle, Vec<Expression>),
5400
5401 /// A type conversion with many arguments.
5402 ConversionBraced(TypeHandle, Vec<Expression>),
5403
5404 /// A braced init list expression.
5405 BracedInitList(Box<Expression>),
5406
5407 /// The `new` operator.
5408 New(Vec<Expression>, TypeHandle, Option<Initializer>),
5409
5410 /// The global `::new` operator.
5411 GlobalNew(Vec<Expression>, TypeHandle, Option<Initializer>),
5412
5413 /// The `new[]` operator.
5414 NewArray(Vec<Expression>, TypeHandle, Option<Initializer>),
5415
5416 /// The global `::new[]` operator.
5417 GlobalNewArray(Vec<Expression>, TypeHandle, Option<Initializer>),
5418
5419 /// The `delete` operator.
5420 Delete(Box<Expression>),
5421
5422 /// The global `::delete` operator.
5423 GlobalDelete(Box<Expression>),
5424
5425 /// The `delete[]` operator.
5426 DeleteArray(Box<Expression>),
5427
5428 /// The global `::delete[]` operator.
5429 GlobalDeleteArray(Box<Expression>),
5430
5431 /// `dynamic_cast<type> (expression)`
5432 DynamicCast(TypeHandle, Box<Expression>),
5433
5434 /// `static_cast<type> (expression)`
5435 StaticCast(TypeHandle, Box<Expression>),
5436
5437 /// `const_cast<type> (expression)`
5438 ConstCast(TypeHandle, Box<Expression>),
5439
5440 /// `reinterpret_cast<type> (expression)`
5441 ReinterpretCast(TypeHandle, Box<Expression>),
5442
5443 /// `typeid (type)`
5444 TypeidType(TypeHandle),
5445
5446 /// `typeid (expression)`
5447 TypeidExpr(Box<Expression>),
5448
5449 /// `sizeof (type)`
5450 SizeofType(TypeHandle),
5451
5452 /// `sizeof (expression)`
5453 SizeofExpr(Box<Expression>),
5454
5455 /// `alignof (type)`
5456 AlignofType(TypeHandle),
5457
5458 /// `alignof (expression)`
5459 AlignofExpr(Box<Expression>),
5460
5461 /// `noexcept (expression)`
5462 Noexcept(Box<Expression>),
5463
5464 /// A named template parameter.
5465 TemplateParam(TemplateParam),
5466
5467 /// A function parameter.
5468 FunctionParam(FunctionParam),
5469
5470 /// `expr.name`
5471 Member(Box<Expression>, MemberName),
5472
5473 /// `expr->name`
5474 DerefMember(Box<Expression>, MemberName),
5475
5476 /// `expr.*expr`
5477 PointerToMember(Box<Expression>, Box<Expression>),
5478
5479 /// `sizeof...(T)`, size of a template parameter pack.
5480 SizeofTemplatePack(TemplateParam),
5481
5482 /// `sizeof...(parameter)`, size of a function parameter pack.
5483 SizeofFunctionPack(FunctionParam),
5484
5485 /// `sizeof...(T)`, size of a captured template parameter pack from an alias
5486 /// template.
5487 SizeofCapturedTemplatePack(Vec<TemplateArg>),
5488
5489 /// `expression...`, pack expansion.
5490 PackExpansion(Box<Expression>),
5491
5492 /// `throw expression`
5493 Throw(Box<Expression>),
5494
5495 /// `throw` with no operand
5496 Rethrow,
5497
5498 /// `f(p)`, `N::f(p)`, `::f(p)`, freestanding dependent name (e.g., `T::x`),
5499 /// objectless nonstatic member reference.
5500 UnresolvedName(UnresolvedName),
5501
5502 /// An `<expr-primary>` production.
5503 Primary(ExprPrimary),
5504 }
5505
5506 impl Parse for Expression {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Expression, IndexStr<'b>)>5507 fn parse<'a, 'b>(
5508 ctx: &'a ParseContext,
5509 subs: &'a mut SubstitutionTable,
5510 input: IndexStr<'b>,
5511 ) -> Result<(Expression, IndexStr<'b>)> {
5512 try_begin_parse!("Expression", ctx, input);
5513
5514 if let Ok(tail) = consume(b"pp_", input) {
5515 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5516 let expr = Expression::PrefixInc(Box::new(expr));
5517 return Ok((expr, tail));
5518 }
5519
5520 if let Ok(tail) = consume(b"mm_", input) {
5521 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5522 let expr = Expression::PrefixDec(Box::new(expr));
5523 return Ok((expr, tail));
5524 }
5525
5526 if let Some((head, tail)) = input.try_split_at(2) {
5527 match head.as_ref() {
5528 b"cl" => {
5529 let (func, tail) = Expression::parse(ctx, subs, tail)?;
5530 let (args, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5531 let tail = consume(b"E", tail)?;
5532 let expr = Expression::Call(Box::new(func), args);
5533 return Ok((expr, tail));
5534 }
5535 b"cv" => {
5536 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5537 if let Ok(tail) = consume(b"_", tail) {
5538 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5539 let tail = consume(b"E", tail)?;
5540 let expr = Expression::ConversionMany(ty, exprs);
5541 return Ok((expr, tail));
5542 } else {
5543 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5544 let expr = Expression::ConversionOne(ty, Box::new(expr));
5545 return Ok((expr, tail));
5546 }
5547 }
5548 b"tl" => {
5549 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5550 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5551 let expr = Expression::ConversionBraced(ty, exprs);
5552 let tail = consume(b"E", tail)?;
5553 return Ok((expr, tail));
5554 }
5555 b"il" => {
5556 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5557 let tail = consume(b"E", tail)?;
5558 let expr = Expression::BracedInitList(Box::new(expr));
5559 return Ok((expr, tail));
5560 }
5561 b"dc" => {
5562 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5563 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5564 let expr = Expression::DynamicCast(ty, Box::new(expr));
5565 return Ok((expr, tail));
5566 }
5567 b"sc" => {
5568 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5569 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5570 let expr = Expression::StaticCast(ty, Box::new(expr));
5571 return Ok((expr, tail));
5572 }
5573 b"cc" => {
5574 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5575 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5576 let expr = Expression::ConstCast(ty, Box::new(expr));
5577 return Ok((expr, tail));
5578 }
5579 b"rc" => {
5580 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5581 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5582 let expr = Expression::ReinterpretCast(ty, Box::new(expr));
5583 return Ok((expr, tail));
5584 }
5585 b"ti" => {
5586 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5587 let expr = Expression::TypeidType(ty);
5588 return Ok((expr, tail));
5589 }
5590 b"te" => {
5591 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5592 let expr = Expression::TypeidExpr(Box::new(expr));
5593 return Ok((expr, tail));
5594 }
5595 b"st" => {
5596 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5597 let expr = Expression::SizeofType(ty);
5598 return Ok((expr, tail));
5599 }
5600 b"sz" => {
5601 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5602 let expr = Expression::SizeofExpr(Box::new(expr));
5603 return Ok((expr, tail));
5604 }
5605 b"at" => {
5606 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5607 let expr = Expression::AlignofType(ty);
5608 return Ok((expr, tail));
5609 }
5610 b"az" => {
5611 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5612 let expr = Expression::AlignofExpr(Box::new(expr));
5613 return Ok((expr, tail));
5614 }
5615 b"nx" => {
5616 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5617 let expr = Expression::Noexcept(Box::new(expr));
5618 return Ok((expr, tail));
5619 }
5620 b"dt" => {
5621 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5622 let (name, tail) = MemberName::parse(ctx, subs, tail)?;
5623 let expr = Expression::Member(Box::new(expr), name);
5624 return Ok((expr, tail));
5625 }
5626 b"pt" => {
5627 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5628 let (name, tail) = MemberName::parse(ctx, subs, tail)?;
5629 let expr = Expression::DerefMember(Box::new(expr), name);
5630 return Ok((expr, tail));
5631 }
5632 b"ds" => {
5633 let (first, tail) = Expression::parse(ctx, subs, tail)?;
5634 let (second, tail) = Expression::parse(ctx, subs, tail)?;
5635 let expr = Expression::PointerToMember(Box::new(first), Box::new(second));
5636 return Ok((expr, tail));
5637 }
5638 b"sZ" => {
5639 if let Ok((param, tail)) = TemplateParam::parse(ctx, subs, tail) {
5640 let expr = Expression::SizeofTemplatePack(param);
5641 return Ok((expr, tail));
5642 }
5643
5644 let (param, tail) = FunctionParam::parse(ctx, subs, tail)?;
5645 let expr = Expression::SizeofFunctionPack(param);
5646 return Ok((expr, tail));
5647 }
5648 b"sP" => {
5649 let (args, tail) = zero_or_more::<TemplateArg>(ctx, subs, tail)?;
5650 let expr = Expression::SizeofCapturedTemplatePack(args);
5651 let tail = consume(b"E", tail)?;
5652 return Ok((expr, tail));
5653 }
5654 b"sp" => {
5655 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5656 let expr = Expression::PackExpansion(Box::new(expr));
5657 return Ok((expr, tail));
5658 }
5659 b"tw" => {
5660 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5661 let expr = Expression::Throw(Box::new(expr));
5662 return Ok((expr, tail));
5663 }
5664 b"tr" => {
5665 let expr = Expression::Rethrow;
5666 return Ok((expr, tail));
5667 }
5668 b"gs" => {
5669 if let Ok((expr, tail)) = can_be_global(true, ctx, subs, tail) {
5670 return Ok((expr, tail));
5671 }
5672 }
5673 _ => {}
5674 }
5675 }
5676
5677 if let Ok((expr, tail)) = can_be_global(false, ctx, subs, input) {
5678 return Ok((expr, tail));
5679 }
5680
5681 if let Ok((param, tail)) = TemplateParam::parse(ctx, subs, input) {
5682 let expr = Expression::TemplateParam(param);
5683 return Ok((expr, tail));
5684 }
5685
5686 if let Ok((param, tail)) = FunctionParam::parse(ctx, subs, input) {
5687 let expr = Expression::FunctionParam(param);
5688 return Ok((expr, tail));
5689 }
5690
5691 if let Ok((name, tail)) = UnresolvedName::parse(ctx, subs, input) {
5692 let expr = Expression::UnresolvedName(name);
5693 return Ok((expr, tail));
5694 }
5695
5696 if let Ok((prim, tail)) = ExprPrimary::parse(ctx, subs, input) {
5697 let expr = Expression::Primary(prim);
5698 return Ok((expr, tail));
5699 }
5700
5701 // "A production for <expression> that directly specifies an operation
5702 // code (e.g., for the -> operator) takes precedence over one that is
5703 // expressed in terms of (unary/binary/ternary) <operator-name>." So try
5704 // and parse unary/binary/ternary expressions last.
5705 let (expr, tail) = OperatorName::parse_from_expr(ctx, subs, input)?;
5706 return Ok((expr, tail));
5707
5708 // Parse the various expressions that can optionally have a leading "gs"
5709 // to indicate that they are in the global namespace. The input is after
5710 // we have already detected consumed the optional "gs" and if we did
5711 // find it, then `is_global` should be true.
5712 fn can_be_global<'a, 'b>(
5713 is_global: bool,
5714 ctx: &'a ParseContext,
5715 subs: &'a mut SubstitutionTable,
5716 input: IndexStr<'b>,
5717 ) -> Result<(Expression, IndexStr<'b>)> {
5718 match input.try_split_at(2) {
5719 None => Err(error::Error::UnexpectedEnd),
5720 Some((head, tail)) => match head.as_ref() {
5721 b"nw" => {
5722 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5723 let tail = consume(b"_", tail)?;
5724 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5725 if let Ok(tail) = consume(b"E", tail) {
5726 let expr = if is_global {
5727 Expression::GlobalNew(exprs, ty, None)
5728 } else {
5729 Expression::New(exprs, ty, None)
5730 };
5731 Ok((expr, tail))
5732 } else {
5733 let (init, tail) = Initializer::parse(ctx, subs, tail)?;
5734 let expr = if is_global {
5735 Expression::GlobalNew(exprs, ty, Some(init))
5736 } else {
5737 Expression::New(exprs, ty, Some(init))
5738 };
5739 Ok((expr, tail))
5740 }
5741 }
5742 b"na" => {
5743 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5744 let tail = consume(b"_", tail)?;
5745 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5746 if let Ok(tail) = consume(b"E", tail) {
5747 let expr = if is_global {
5748 Expression::GlobalNewArray(exprs, ty, None)
5749 } else {
5750 Expression::NewArray(exprs, ty, None)
5751 };
5752 Ok((expr, tail))
5753 } else {
5754 let (init, tail) = Initializer::parse(ctx, subs, tail)?;
5755 let expr = if is_global {
5756 Expression::GlobalNewArray(exprs, ty, Some(init))
5757 } else {
5758 Expression::NewArray(exprs, ty, Some(init))
5759 };
5760 Ok((expr, tail))
5761 }
5762 }
5763 b"dl" => {
5764 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5765 let expr = if is_global {
5766 Expression::GlobalDelete(Box::new(expr))
5767 } else {
5768 Expression::Delete(Box::new(expr))
5769 };
5770 Ok((expr, tail))
5771 }
5772 b"da" => {
5773 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5774 let expr = if is_global {
5775 Expression::GlobalDeleteArray(Box::new(expr))
5776 } else {
5777 Expression::DeleteArray(Box::new(expr))
5778 };
5779 Ok((expr, tail))
5780 }
5781 _ => Err(error::Error::UnexpectedText),
5782 },
5783 }
5784 }
5785 }
5786 }
5787
5788 impl<'subs, W> Demangle<'subs, W> for Expression
5789 where
5790 W: 'subs + DemangleWrite,
5791 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result5792 fn demangle<'prev, 'ctx>(
5793 &'subs self,
5794 ctx: &'ctx mut DemangleContext<'subs, W>,
5795 scope: Option<ArgScopeStack<'prev, 'subs>>,
5796 ) -> fmt::Result {
5797 let ctx = try_begin_demangle!(self, ctx, scope);
5798
5799 match *self {
5800 Expression::Unary(OperatorName::Simple(ref op), ref expr)
5801 if *op == SimpleOperatorName::PostInc || *op == SimpleOperatorName::PostDec =>
5802 {
5803 expr.demangle_as_subexpr(ctx, scope)?;
5804 op.demangle(ctx, scope)
5805 }
5806 Expression::Unary(ref op, ref expr) => {
5807 op.demangle(ctx, scope)?;
5808 expr.demangle_as_subexpr(ctx, scope)
5809 }
5810 // These need an extra set of parens so that it doesn't close any
5811 // template argument accidentally.
5812 Expression::Binary(
5813 OperatorName::Simple(SimpleOperatorName::Greater),
5814 ref lhs,
5815 ref rhs,
5816 ) => {
5817 write!(ctx, "((")?;
5818 lhs.demangle(ctx, scope)?;
5819 write!(ctx, ")>(")?;
5820 rhs.demangle(ctx, scope)?;
5821 write!(ctx, "))")
5822 }
5823 Expression::Binary(ref op, ref lhs, ref rhs) => {
5824 lhs.demangle_as_subexpr(ctx, scope)?;
5825 op.demangle(ctx, scope)?;
5826 rhs.demangle_as_subexpr(ctx, scope)
5827 }
5828 Expression::Ternary(
5829 OperatorName::Simple(SimpleOperatorName::Question),
5830 ref condition,
5831 ref consequent,
5832 ref alternative,
5833 ) => {
5834 condition.demangle_as_subexpr(ctx, scope)?;
5835 write!(ctx, "?")?;
5836 consequent.demangle_as_subexpr(ctx, scope)?;
5837 write!(ctx, " : ")?;
5838 alternative.demangle_as_subexpr(ctx, scope)
5839 }
5840 Expression::Ternary(ref op, ref e1, ref e2, ref e3) => {
5841 // Nonsensical ternary operator? Just print it like a function call,
5842 // I suppose...
5843 //
5844 // TODO: should we detect and reject this during parsing?
5845 op.demangle(ctx, scope)?;
5846 write!(ctx, "(")?;
5847 e1.demangle(ctx, scope)?;
5848 write!(ctx, ", ")?;
5849 e2.demangle(ctx, scope)?;
5850 write!(ctx, ", ")?;
5851 e3.demangle(ctx, scope)?;
5852 write!(ctx, ")")?;
5853 Ok(())
5854 }
5855 Expression::PrefixInc(ref expr) => {
5856 write!(ctx, "++")?;
5857 expr.demangle(ctx, scope)
5858 }
5859 Expression::PrefixDec(ref expr) => {
5860 write!(ctx, "--")?;
5861 expr.demangle(ctx, scope)
5862 }
5863 Expression::Call(ref functor_expr, ref args) => {
5864 functor_expr.demangle_as_subexpr(ctx, scope)?;
5865 write!(ctx, "(")?;
5866 let mut need_comma = false;
5867 for arg in args {
5868 if need_comma {
5869 write!(ctx, ", ")?;
5870 }
5871 arg.demangle(ctx, scope)?;
5872 need_comma = true;
5873 }
5874 write!(ctx, ")")?;
5875 Ok(())
5876 }
5877 Expression::ConversionOne(ref ty, ref expr) => {
5878 write!(ctx, "(")?;
5879 ty.demangle(ctx, scope)?;
5880 write!(ctx, ")(")?;
5881 expr.demangle(ctx, scope)?;
5882 write!(ctx, ")")?;
5883 Ok(())
5884 }
5885 Expression::ConversionMany(ref ty, ref exprs) => {
5886 ty.demangle(ctx, scope)?;
5887 write!(ctx, "(")?;
5888 let mut need_comma = false;
5889 for expr in exprs {
5890 if need_comma {
5891 write!(ctx, ", ")?;
5892 }
5893 expr.demangle(ctx, scope)?;
5894 need_comma = true;
5895 }
5896 write!(ctx, ")")?;
5897 Ok(())
5898 }
5899 Expression::ConversionBraced(ref ty, ref exprs) => {
5900 ty.demangle(ctx, scope)?;
5901 write!(ctx, "{{")?;
5902 let mut need_comma = false;
5903 for expr in exprs {
5904 if need_comma {
5905 write!(ctx, ", ")?;
5906 }
5907 expr.demangle(ctx, scope)?;
5908 need_comma = true;
5909 }
5910 write!(ctx, "}}")?;
5911 Ok(())
5912 }
5913 Expression::BracedInitList(ref expr) => {
5914 write!(ctx, "{{")?;
5915 expr.demangle(ctx, scope)?;
5916 write!(ctx, "}}")?;
5917 Ok(())
5918 }
5919 // TODO: factor out all this duplication in the `new` variants.
5920 Expression::New(ref exprs, ref ty, ref init) => {
5921 write!(ctx, "new (")?;
5922 let mut need_comma = false;
5923 for expr in exprs {
5924 if need_comma {
5925 write!(ctx, ", ")?;
5926 }
5927 expr.demangle(ctx, scope)?;
5928 need_comma = true;
5929 }
5930 write!(ctx, ") ")?;
5931 ty.demangle(ctx, scope)?;
5932 if let Some(ref init) = *init {
5933 init.demangle(ctx, scope)?;
5934 }
5935 Ok(())
5936 }
5937 Expression::GlobalNew(ref exprs, ref ty, ref init) => {
5938 write!(ctx, "::new (")?;
5939 let mut need_comma = false;
5940 for expr in exprs {
5941 if need_comma {
5942 write!(ctx, ", ")?;
5943 }
5944 expr.demangle(ctx, scope)?;
5945 need_comma = true;
5946 }
5947 write!(ctx, ") ")?;
5948 ty.demangle(ctx, scope)?;
5949 if let Some(ref init) = *init {
5950 init.demangle(ctx, scope)?;
5951 }
5952 Ok(())
5953 }
5954 Expression::NewArray(ref exprs, ref ty, ref init) => {
5955 write!(ctx, "new[] (")?;
5956 let mut need_comma = false;
5957 for expr in exprs {
5958 if need_comma {
5959 write!(ctx, ", ")?;
5960 }
5961 expr.demangle(ctx, scope)?;
5962 need_comma = true;
5963 }
5964 write!(ctx, ") ")?;
5965 ty.demangle(ctx, scope)?;
5966 if let Some(ref init) = *init {
5967 init.demangle(ctx, scope)?;
5968 }
5969 Ok(())
5970 }
5971 Expression::GlobalNewArray(ref exprs, ref ty, ref init) => {
5972 write!(ctx, "::new[] (")?;
5973 let mut need_comma = false;
5974 for expr in exprs {
5975 if need_comma {
5976 write!(ctx, ", ")?;
5977 }
5978 expr.demangle(ctx, scope)?;
5979 need_comma = true;
5980 }
5981 write!(ctx, ") ")?;
5982 ty.demangle(ctx, scope)?;
5983 if let Some(ref init) = *init {
5984 init.demangle(ctx, scope)?;
5985 }
5986 Ok(())
5987 }
5988 Expression::Delete(ref expr) => {
5989 write!(ctx, "delete ")?;
5990 expr.demangle(ctx, scope)
5991 }
5992 Expression::GlobalDelete(ref expr) => {
5993 write!(ctx, "::delete ")?;
5994 expr.demangle(ctx, scope)
5995 }
5996 Expression::DeleteArray(ref expr) => {
5997 write!(ctx, "delete[] ")?;
5998 expr.demangle(ctx, scope)
5999 }
6000 Expression::GlobalDeleteArray(ref expr) => {
6001 write!(ctx, "::delete[] ")?;
6002 expr.demangle(ctx, scope)
6003 }
6004 // TODO: factor out duplicated code from cast variants.
6005 Expression::DynamicCast(ref ty, ref expr) => {
6006 write!(ctx, "dynamic_cast<")?;
6007 ty.demangle(ctx, scope)?;
6008 write!(ctx, ">(")?;
6009 expr.demangle(ctx, scope)?;
6010 write!(ctx, ")")?;
6011 Ok(())
6012 }
6013 Expression::StaticCast(ref ty, ref expr) => {
6014 write!(ctx, "static_cast<")?;
6015 ty.demangle(ctx, scope)?;
6016 write!(ctx, ">(")?;
6017 expr.demangle(ctx, scope)?;
6018 write!(ctx, ")")?;
6019 Ok(())
6020 }
6021 Expression::ConstCast(ref ty, ref expr) => {
6022 write!(ctx, "const_cast<")?;
6023 ty.demangle(ctx, scope)?;
6024 write!(ctx, ">(")?;
6025 expr.demangle(ctx, scope)?;
6026 write!(ctx, ")")?;
6027 Ok(())
6028 }
6029 Expression::ReinterpretCast(ref ty, ref expr) => {
6030 write!(ctx, "reinterpret_cast<")?;
6031 ty.demangle(ctx, scope)?;
6032 write!(ctx, ">(")?;
6033 expr.demangle(ctx, scope)?;
6034 write!(ctx, ")")?;
6035 Ok(())
6036 }
6037 Expression::TypeidType(ref ty) => {
6038 write!(ctx, "typeid (")?;
6039 ty.demangle(ctx, scope)?;
6040 write!(ctx, ")")?;
6041 Ok(())
6042 }
6043 Expression::TypeidExpr(ref expr) => {
6044 write!(ctx, "typeid (")?;
6045 expr.demangle(ctx, scope)?;
6046 write!(ctx, ")")?;
6047 Ok(())
6048 }
6049 Expression::SizeofType(ref ty) => {
6050 write!(ctx, "sizeof (")?;
6051 ty.demangle(ctx, scope)?;
6052 write!(ctx, ")")?;
6053 Ok(())
6054 }
6055 Expression::SizeofExpr(ref expr) => {
6056 write!(ctx, "sizeof (")?;
6057 expr.demangle(ctx, scope)?;
6058 write!(ctx, ")")?;
6059 Ok(())
6060 }
6061 Expression::AlignofType(ref ty) => {
6062 write!(ctx, "alignof (")?;
6063 ty.demangle(ctx, scope)?;
6064 write!(ctx, ")")?;
6065 Ok(())
6066 }
6067 Expression::AlignofExpr(ref expr) => {
6068 write!(ctx, "alignof (")?;
6069 expr.demangle(ctx, scope)?;
6070 write!(ctx, ")")?;
6071 Ok(())
6072 }
6073 Expression::Noexcept(ref expr) => {
6074 write!(ctx, "noexcept (")?;
6075 expr.demangle(ctx, scope)?;
6076 write!(ctx, ")")?;
6077 Ok(())
6078 }
6079 Expression::TemplateParam(ref param) => param.demangle(ctx, scope),
6080 Expression::FunctionParam(ref param) => param.demangle(ctx, scope),
6081 Expression::Member(ref expr, ref name) => {
6082 expr.demangle_as_subexpr(ctx, scope)?;
6083 write!(ctx, ".")?;
6084 name.demangle(ctx, scope)
6085 }
6086 Expression::DerefMember(ref expr, ref name) => {
6087 expr.demangle(ctx, scope)?;
6088 write!(ctx, "->")?;
6089 name.demangle(ctx, scope)
6090 }
6091 Expression::PointerToMember(ref e1, ref e2) => {
6092 e1.demangle(ctx, scope)?;
6093 write!(ctx, ".*")?;
6094 e2.demangle(ctx, scope)
6095 }
6096 Expression::SizeofTemplatePack(ref param) => {
6097 write!(ctx, "sizeof...(")?;
6098 param.demangle(ctx, scope)?;
6099 write!(ctx, ")")?;
6100 Ok(())
6101 }
6102 Expression::SizeofFunctionPack(ref param) => {
6103 write!(ctx, "sizeof...(")?;
6104 param.demangle(ctx, scope)?;
6105 write!(ctx, ")")?;
6106 Ok(())
6107 }
6108 Expression::SizeofCapturedTemplatePack(ref args) => {
6109 write!(ctx, "sizeof...(")?;
6110 let mut need_comma = false;
6111 for arg in args {
6112 if need_comma {
6113 write!(ctx, ", ")?;
6114 }
6115 arg.demangle(ctx, scope)?;
6116 need_comma = true;
6117 }
6118 write!(ctx, ")")?;
6119 Ok(())
6120 }
6121 Expression::PackExpansion(ref pack) => {
6122 pack.demangle_as_subexpr(ctx, scope)?;
6123 write!(ctx, "...")?;
6124 Ok(())
6125 }
6126 Expression::Throw(ref expr) => {
6127 write!(ctx, "throw ")?;
6128 expr.demangle(ctx, scope)
6129 }
6130 Expression::Rethrow => {
6131 write!(ctx, "throw")?;
6132 Ok(())
6133 }
6134 Expression::UnresolvedName(ref name) => name.demangle(ctx, scope),
6135 Expression::Primary(ref expr) => expr.demangle(ctx, scope),
6136 }
6137 }
6138 }
6139
6140 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 + DemangleWrite,6141 fn demangle_as_subexpr<'subs, 'prev, 'ctx, W>(
6142 &'subs self,
6143 ctx: &'ctx mut DemangleContext<'subs, W>,
6144 scope: Option<ArgScopeStack<'prev, 'subs>>,
6145 ) -> fmt::Result
6146 where
6147 W: 'subs + DemangleWrite,
6148 {
6149 let needs_parens = match *self {
6150 Expression::FunctionParam(_) | Expression::Primary(ExprPrimary::External(_)) => false,
6151 _ => true,
6152 };
6153
6154 if needs_parens {
6155 write!(ctx, "(")?;
6156 }
6157
6158 self.demangle(ctx, scope)?;
6159
6160 if needs_parens {
6161 write!(ctx, ")")?;
6162 }
6163
6164 Ok(())
6165 }
6166 }
6167
6168 /// The `<unresolved-name>` production.
6169 ///
6170 /// ```text
6171 /// <unresolved-name> ::= [gs] <base-unresolved-name>
6172 /// #
6173 /// ::= sr <unresolved-type> <base-unresolved-name>
6174 /// #
6175 /// ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
6176 /// #
6177 /// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
6178 /// # A::x, N::y, A<T>::z; "gs" means leading "::"
6179 /// ```
6180 #[derive(Clone, Debug, PartialEq, Eq)]
6181 pub enum UnresolvedName {
6182 /// `x`
6183 Name(BaseUnresolvedName),
6184
6185 /// `::x`
6186 Global(BaseUnresolvedName),
6187
6188 /// `T::x` or `decltype(p)::x` or `T::N::x` or `decltype(p)::N::x`
6189 Nested1(
6190 UnresolvedTypeHandle,
6191 Vec<UnresolvedQualifierLevel>,
6192 BaseUnresolvedName,
6193 ),
6194
6195 /// `A::x` or `N::y` or `A<T>::z`
6196 Nested2(Vec<UnresolvedQualifierLevel>, BaseUnresolvedName),
6197
6198 /// `::A::x` or `::N::y` or `::A<T>::z`
6199 GlobalNested2(Vec<UnresolvedQualifierLevel>, BaseUnresolvedName),
6200 }
6201
6202 impl Parse for UnresolvedName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(UnresolvedName, IndexStr<'b>)>6203 fn parse<'a, 'b>(
6204 ctx: &'a ParseContext,
6205 subs: &'a mut SubstitutionTable,
6206 input: IndexStr<'b>,
6207 ) -> Result<(UnresolvedName, IndexStr<'b>)> {
6208 try_begin_parse!("UnresolvedName", ctx, input);
6209
6210 if let Ok(tail) = consume(b"gs", input) {
6211 if let Ok((name, tail)) = BaseUnresolvedName::parse(ctx, subs, tail) {
6212 return Ok((UnresolvedName::Global(name), tail));
6213 }
6214
6215 let tail = consume(b"sr", tail)?;
6216 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6217 let tail = consume(b"E", tail)?;
6218 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6219 return Ok((UnresolvedName::GlobalNested2(levels, name), tail));
6220 }
6221
6222 if let Ok((name, tail)) = BaseUnresolvedName::parse(ctx, subs, input) {
6223 return Ok((UnresolvedName::Name(name), tail));
6224 }
6225
6226 let tail = consume(b"sr", input)?;
6227
6228 if tail.peek() == Some(b'N') {
6229 let tail = consume(b"N", tail).unwrap();
6230 let (ty, tail) = UnresolvedTypeHandle::parse(ctx, subs, tail)?;
6231 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6232 let tail = consume(b"E", tail)?;
6233 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6234 return Ok((UnresolvedName::Nested1(ty, levels, name), tail));
6235 }
6236
6237 if let Ok((ty, tail)) = UnresolvedTypeHandle::parse(ctx, subs, tail) {
6238 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6239 return Ok((UnresolvedName::Nested1(ty, vec![], name), tail));
6240 }
6241
6242 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6243 let tail = consume(b"E", tail)?;
6244 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6245 Ok((UnresolvedName::Nested2(levels, name), tail))
6246 }
6247 }
6248
6249 impl<'subs, W> Demangle<'subs, W> for UnresolvedName
6250 where
6251 W: 'subs + DemangleWrite,
6252 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6253 fn demangle<'prev, 'ctx>(
6254 &'subs self,
6255 ctx: &'ctx mut DemangleContext<'subs, W>,
6256 scope: Option<ArgScopeStack<'prev, 'subs>>,
6257 ) -> fmt::Result {
6258 let ctx = try_begin_demangle!(self, ctx, scope);
6259
6260 match *self {
6261 UnresolvedName::Name(ref name) => name.demangle(ctx, scope),
6262 UnresolvedName::Global(ref name) => {
6263 write!(ctx, "::")?;
6264 name.demangle(ctx, scope)
6265 }
6266 UnresolvedName::Nested1(ref ty, ref levels, ref name) => {
6267 ty.demangle(ctx, scope)?;
6268 write!(ctx, "::")?;
6269 for lvl in &levels[..] {
6270 lvl.demangle(ctx, scope)?;
6271 write!(ctx, "::")?;
6272 }
6273 name.demangle(ctx, scope)
6274 }
6275 UnresolvedName::Nested2(ref levels, ref name) => {
6276 for lvl in &levels[..] {
6277 lvl.demangle(ctx, scope)?;
6278 write!(ctx, "::")?;
6279 }
6280 name.demangle(ctx, scope)
6281 }
6282 // `::A::x` or `::N::y` or `::A<T>::z`
6283 UnresolvedName::GlobalNested2(ref levels, ref name) => {
6284 write!(ctx, "::")?;
6285 for lvl in &levels[..] {
6286 lvl.demangle(ctx, scope)?;
6287 write!(ctx, "::")?;
6288 }
6289 name.demangle(ctx, scope)
6290 }
6291 }
6292 }
6293 }
6294
6295 /// The `<unresolved-type>` production.
6296 ///
6297 /// ```text
6298 /// <unresolved-type> ::= <template-param> [ <template-args> ] # T:: or T<X,Y>::
6299 /// ::= <decltype> # decltype(p)::
6300 /// ::= <substitution>
6301 /// ```
6302 #[derive(Clone, Debug, PartialEq, Eq)]
6303 pub enum UnresolvedType {
6304 /// An unresolved template type.
6305 Template(TemplateParam, Option<TemplateArgs>),
6306
6307 /// An unresolved `decltype`.
6308 Decltype(Decltype),
6309 }
6310
6311 define_handle! {
6312 /// A reference to a parsed `<unresolved-type>` production.
6313 pub enum UnresolvedTypeHandle
6314 }
6315
6316 impl Parse for UnresolvedTypeHandle {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(UnresolvedTypeHandle, IndexStr<'b>)>6317 fn parse<'a, 'b>(
6318 ctx: &'a ParseContext,
6319 subs: &'a mut SubstitutionTable,
6320 input: IndexStr<'b>,
6321 ) -> Result<(UnresolvedTypeHandle, IndexStr<'b>)> {
6322 try_begin_parse!("UnresolvedTypeHandle", ctx, input);
6323
6324 if let Ok((param, tail)) = TemplateParam::parse(ctx, subs, input) {
6325 let (args, tail) = if let Ok((args, tail)) = TemplateArgs::parse(ctx, subs, tail) {
6326 (Some(args), tail)
6327 } else {
6328 (None, tail)
6329 };
6330 let ty = UnresolvedType::Template(param, args);
6331 let ty = Substitutable::UnresolvedType(ty);
6332 let idx = subs.insert(ty);
6333 let handle = UnresolvedTypeHandle::BackReference(idx);
6334 return Ok((handle, tail));
6335 }
6336
6337 if let Ok((decltype, tail)) = Decltype::parse(ctx, subs, input) {
6338 let ty = UnresolvedType::Decltype(decltype);
6339 let ty = Substitutable::UnresolvedType(ty);
6340 let idx = subs.insert(ty);
6341 let handle = UnresolvedTypeHandle::BackReference(idx);
6342 return Ok((handle, tail));
6343 }
6344
6345 let (sub, tail) = Substitution::parse(ctx, subs, input)?;
6346 match sub {
6347 Substitution::WellKnown(component) => {
6348 Ok((UnresolvedTypeHandle::WellKnown(component), tail))
6349 }
6350 Substitution::BackReference(idx) => {
6351 // TODO: should this check that the back reference actually
6352 // points to an `<unresolved-type>`?
6353 Ok((UnresolvedTypeHandle::BackReference(idx), tail))
6354 }
6355 }
6356 }
6357 }
6358
6359 impl<'subs, W> Demangle<'subs, W> for UnresolvedType
6360 where
6361 W: 'subs + DemangleWrite,
6362 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6363 fn demangle<'prev, 'ctx>(
6364 &'subs self,
6365 ctx: &'ctx mut DemangleContext<'subs, W>,
6366 scope: Option<ArgScopeStack<'prev, 'subs>>,
6367 ) -> fmt::Result {
6368 let ctx = try_begin_demangle!(self, ctx, scope);
6369
6370 match *self {
6371 UnresolvedType::Decltype(ref dt) => dt.demangle(ctx, scope),
6372 UnresolvedType::Template(ref param, ref args) => {
6373 if let Some(ref args) = *args {
6374 let scope = scope.push(args);
6375 param.demangle(ctx, scope)?;
6376 args.demangle(ctx, scope)?;
6377 } else {
6378 param.demangle(ctx, scope)?;
6379 }
6380 Ok(())
6381 }
6382 }
6383 }
6384 }
6385
6386 /// The `<unresolved-qualifier-level>` production.
6387 ///
6388 /// ```text
6389 /// <unresolved-qualifier-level> ::= <simple-id>
6390 /// ```
6391 #[derive(Clone, Debug, PartialEq, Eq)]
6392 pub struct UnresolvedQualifierLevel(SimpleId);
6393
6394 impl Parse for UnresolvedQualifierLevel {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(UnresolvedQualifierLevel, IndexStr<'b>)>6395 fn parse<'a, 'b>(
6396 ctx: &'a ParseContext,
6397 subs: &'a mut SubstitutionTable,
6398 input: IndexStr<'b>,
6399 ) -> Result<(UnresolvedQualifierLevel, IndexStr<'b>)> {
6400 try_begin_parse!("UnresolvedQualifierLevel", ctx, input);
6401
6402 let (id, tail) = SimpleId::parse(ctx, subs, input)?;
6403 Ok((UnresolvedQualifierLevel(id), tail))
6404 }
6405 }
6406
6407 impl<'subs, W> Demangle<'subs, W> for UnresolvedQualifierLevel
6408 where
6409 W: 'subs + DemangleWrite,
6410 {
6411 #[inline]
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6412 fn demangle<'prev, 'ctx>(
6413 &'subs self,
6414 ctx: &'ctx mut DemangleContext<'subs, W>,
6415 scope: Option<ArgScopeStack<'prev, 'subs>>,
6416 ) -> fmt::Result {
6417 let ctx = try_begin_demangle!(self, ctx, scope);
6418
6419 self.0.demangle(ctx, scope)
6420 }
6421 }
6422
6423 /// The `<simple-id>` production.
6424 ///
6425 /// ```text
6426 /// <simple-id> ::= <source-name> [ <template-args> ]
6427 /// ```
6428 #[derive(Clone, Debug, PartialEq, Eq)]
6429 pub struct SimpleId(SourceName, Option<TemplateArgs>);
6430
6431 impl Parse for SimpleId {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(SimpleId, IndexStr<'b>)>6432 fn parse<'a, 'b>(
6433 ctx: &'a ParseContext,
6434 subs: &'a mut SubstitutionTable,
6435 input: IndexStr<'b>,
6436 ) -> Result<(SimpleId, IndexStr<'b>)> {
6437 try_begin_parse!("SimpleId", ctx, input);
6438
6439 let (name, tail) = SourceName::parse(ctx, subs, input)?;
6440 let (args, tail) = if let Ok((args, tail)) = TemplateArgs::parse(ctx, subs, tail) {
6441 (Some(args), tail)
6442 } else {
6443 (None, tail)
6444 };
6445 Ok((SimpleId(name, args), tail))
6446 }
6447 }
6448
6449 impl<'subs, W> Demangle<'subs, W> for SimpleId
6450 where
6451 W: 'subs + DemangleWrite,
6452 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6453 fn demangle<'prev, 'ctx>(
6454 &'subs self,
6455 ctx: &'ctx mut DemangleContext<'subs, W>,
6456 scope: Option<ArgScopeStack<'prev, 'subs>>,
6457 ) -> fmt::Result {
6458 let ctx = try_begin_demangle!(self, ctx, scope);
6459
6460 self.0.demangle(ctx, scope)?;
6461 if let Some(ref args) = self.1 {
6462 args.demangle(ctx, scope)?;
6463 }
6464 Ok(())
6465 }
6466 }
6467
6468 /// The `<base-unresolved-name>` production.
6469 ///
6470 /// ```text
6471 /// <base-unresolved-name> ::= <simple-id> # unresolved name
6472 /// ::= on <operator-name> # unresolved operator-function-id
6473 /// ::= on <operator-name> <template-args> # unresolved operator template-id
6474 /// ::= dn <destructor-name> # destructor or pseudo-destructor;
6475 /// # e.g. ~X or ~X<N-1>
6476 /// ```
6477 #[derive(Clone, Debug, PartialEq, Eq)]
6478 pub enum BaseUnresolvedName {
6479 /// An unresolved name.
6480 Name(SimpleId),
6481
6482 /// An unresolved function or template function name.
6483 Operator(OperatorName, Option<TemplateArgs>),
6484
6485 /// An unresolved destructor name.
6486 Destructor(DestructorName),
6487 }
6488
6489 impl Parse for BaseUnresolvedName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(BaseUnresolvedName, IndexStr<'b>)>6490 fn parse<'a, 'b>(
6491 ctx: &'a ParseContext,
6492 subs: &'a mut SubstitutionTable,
6493 input: IndexStr<'b>,
6494 ) -> Result<(BaseUnresolvedName, IndexStr<'b>)> {
6495 try_begin_parse!("BaseUnresolvedName", ctx, input);
6496
6497 if let Ok((name, tail)) = SimpleId::parse(ctx, subs, input) {
6498 return Ok((BaseUnresolvedName::Name(name), tail));
6499 }
6500
6501 if let Ok(tail) = consume(b"on", input) {
6502 let (opname, tail) = OperatorName::parse(ctx, subs, tail)?;
6503 let (args, tail) = if let Ok((args, tail)) = TemplateArgs::parse(ctx, subs, tail) {
6504 (Some(args), tail)
6505 } else {
6506 (None, tail)
6507 };
6508 return Ok((BaseUnresolvedName::Operator(opname, args), tail));
6509 }
6510
6511 let tail = consume(b"dn", input)?;
6512 let (name, tail) = DestructorName::parse(ctx, subs, tail)?;
6513 Ok((BaseUnresolvedName::Destructor(name), tail))
6514 }
6515 }
6516
6517 impl<'subs, W> Demangle<'subs, W> for BaseUnresolvedName
6518 where
6519 W: 'subs + DemangleWrite,
6520 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6521 fn demangle<'prev, 'ctx>(
6522 &'subs self,
6523 ctx: &'ctx mut DemangleContext<'subs, W>,
6524 scope: Option<ArgScopeStack<'prev, 'subs>>,
6525 ) -> fmt::Result {
6526 let ctx = try_begin_demangle!(self, ctx, scope);
6527
6528 match *self {
6529 BaseUnresolvedName::Name(ref name) => name.demangle(ctx, scope),
6530 BaseUnresolvedName::Destructor(ref dtor) => dtor.demangle(ctx, scope),
6531 BaseUnresolvedName::Operator(ref op, ref args) => {
6532 op.demangle(ctx, scope)?;
6533 if let Some(ref args) = *args {
6534 args.demangle(ctx, scope)?;
6535 }
6536 Ok(())
6537 }
6538 }
6539 }
6540 }
6541
6542 /// The `<destructor-name>` production.
6543 ///
6544 /// ```text
6545 /// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
6546 /// ::= <simple-id> # e.g., ~A<2*N>
6547 /// ```
6548 #[derive(Clone, Debug, PartialEq, Eq)]
6549 pub enum DestructorName {
6550 /// A destructor for an unresolved type.
6551 Unresolved(UnresolvedTypeHandle),
6552
6553 /// A destructor for a resolved type name.
6554 Name(SimpleId),
6555 }
6556
6557 impl Parse for DestructorName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(DestructorName, IndexStr<'b>)>6558 fn parse<'a, 'b>(
6559 ctx: &'a ParseContext,
6560 subs: &'a mut SubstitutionTable,
6561 input: IndexStr<'b>,
6562 ) -> Result<(DestructorName, IndexStr<'b>)> {
6563 try_begin_parse!("DestructorName", ctx, input);
6564
6565 if let Ok((ty, tail)) = UnresolvedTypeHandle::parse(ctx, subs, input) {
6566 return Ok((DestructorName::Unresolved(ty), tail));
6567 }
6568
6569 let (name, tail) = SimpleId::parse(ctx, subs, input)?;
6570 Ok((DestructorName::Name(name), tail))
6571 }
6572 }
6573
6574 impl<'subs, W> Demangle<'subs, W> for DestructorName
6575 where
6576 W: 'subs + DemangleWrite,
6577 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6578 fn demangle<'prev, 'ctx>(
6579 &'subs self,
6580 ctx: &'ctx mut DemangleContext<'subs, W>,
6581 scope: Option<ArgScopeStack<'prev, 'subs>>,
6582 ) -> fmt::Result {
6583 let ctx = try_begin_demangle!(self, ctx, scope);
6584
6585 write!(ctx, "~")?;
6586 match *self {
6587 DestructorName::Unresolved(ref ty) => ty.demangle(ctx, scope),
6588 DestructorName::Name(ref name) => name.demangle(ctx, scope),
6589 }
6590 }
6591 }
6592
6593 /// The `<expr-primary>` production.
6594 ///
6595 /// ```text
6596 /// <expr-primary> ::= L <type> <value number> E # integer literal
6597 /// ::= L <type> <value float> E # floating literal
6598 /// ::= L <string type> E # string literal
6599 /// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
6600 /// ::= L <pointer type> 0 E # null pointer template argument
6601 /// ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
6602 /// ::= L <mangled-name> E # external name
6603 /// ```
6604 #[derive(Clone, Debug, PartialEq, Eq)]
6605 pub enum ExprPrimary {
6606 /// A type literal.
6607 Literal(TypeHandle, usize, usize),
6608
6609 /// An external name.
6610 External(MangledName),
6611 }
6612
6613 impl Parse for ExprPrimary {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(ExprPrimary, IndexStr<'b>)>6614 fn parse<'a, 'b>(
6615 ctx: &'a ParseContext,
6616 subs: &'a mut SubstitutionTable,
6617 input: IndexStr<'b>,
6618 ) -> Result<(ExprPrimary, IndexStr<'b>)> {
6619 try_begin_parse!("ExprPrimary", ctx, input);
6620
6621 let tail = consume(b"L", input)?;
6622
6623 if let Ok((ty, tail)) = TypeHandle::parse(ctx, subs, tail) {
6624 let start = tail.index();
6625 let num_bytes_in_literal = tail.as_ref().iter().take_while(|&&c| c != b'E').count();
6626 let tail = tail.range_from(num_bytes_in_literal..);
6627 let end = tail.index();
6628 let tail = consume(b"E", tail)?;
6629 let expr = ExprPrimary::Literal(ty, start, end);
6630 return Ok((expr, tail));
6631 }
6632
6633 let (name, tail) = MangledName::parse(ctx, subs, tail)?;
6634 let tail = consume(b"E", tail)?;
6635 let expr = ExprPrimary::External(name);
6636 Ok((expr, tail))
6637 }
6638 }
6639
6640 impl<'subs, W> Demangle<'subs, W> for ExprPrimary
6641 where
6642 W: 'subs + DemangleWrite,
6643 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6644 fn demangle<'prev, 'ctx>(
6645 &'subs self,
6646 ctx: &'ctx mut DemangleContext<'subs, W>,
6647 scope: Option<ArgScopeStack<'prev, 'subs>>,
6648 ) -> fmt::Result {
6649 let ctx = try_begin_demangle!(self, ctx, scope);
6650
6651 fn write_literal<W>(ctx: &mut DemangleContext<W>, start: usize, end: usize) -> fmt::Result
6652 where
6653 W: DemangleWrite,
6654 {
6655 debug_assert!(start <= end);
6656 let start = if start < end && ctx.input[start] == b'n' {
6657 write!(ctx, "-")?;
6658 start + 1
6659 } else {
6660 start
6661 };
6662 let s = ::std::str::from_utf8(&ctx.input[start..end]).map_err(|e| {
6663 log!("Error writing literal: {}", e);
6664 fmt::Error
6665 })?;
6666 ctx.write_str(s)
6667 }
6668
6669 match *self {
6670 ExprPrimary::External(ref name) => {
6671 let saved_show_params = ctx.show_params;
6672 ctx.show_params = true;
6673 let ret = name.demangle(ctx, scope);
6674 ctx.show_params = saved_show_params;
6675 ret
6676 }
6677 ExprPrimary::Literal(
6678 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Bool)),
6679 start,
6680 end,
6681 ) => match &ctx.input[start..end] {
6682 b"0" => write!(ctx, "false"),
6683 b"1" => write!(ctx, "true"),
6684 _ => {
6685 write!(ctx, "(bool)")?;
6686 write_literal(ctx, start, end)
6687 }
6688 },
6689 ExprPrimary::Literal(
6690 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Nullptr)),
6691 _,
6692 _,
6693 ) => write!(ctx, "nullptr"),
6694 ExprPrimary::Literal(
6695 ref ty @ TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Double)),
6696 start,
6697 end,
6698 )
6699 | ExprPrimary::Literal(
6700 ref ty @ TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Float)),
6701 start,
6702 end,
6703 ) => {
6704 write!(ctx, "(")?;
6705 ty.demangle(ctx, scope)?;
6706 let start = if start < end && ctx.input[start] == b'n' {
6707 write!(ctx, ")-[")?;
6708 start + 1
6709 } else {
6710 write!(ctx, ")[")?;
6711 start
6712 };
6713 let s = ::std::str::from_utf8(&ctx.input[start..end]).map_err(|e| {
6714 log!("Error writing literal: {}", e);
6715 fmt::Error
6716 })?;
6717 ctx.write_str(s)?;
6718 write!(ctx, "]")
6719 }
6720 ExprPrimary::Literal(
6721 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int)),
6722 start,
6723 end,
6724 ) => write_literal(ctx, start, end),
6725 ExprPrimary::Literal(ref ty, start, end) => {
6726 write!(ctx, "(")?;
6727 ty.demangle(ctx, scope)?;
6728 write!(ctx, ")")?;
6729 write_literal(ctx, start, end)
6730 }
6731 }
6732 }
6733 }
6734
6735 /// The `<initializer>` production.
6736 ///
6737 /// ```text
6738 /// <initializer> ::= pi <expression>* E # parenthesized initialization
6739 /// ```
6740 #[derive(Clone, Debug, PartialEq, Eq)]
6741 pub struct Initializer(Vec<Expression>);
6742
6743 impl Parse for Initializer {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Initializer, IndexStr<'b>)>6744 fn parse<'a, 'b>(
6745 ctx: &'a ParseContext,
6746 subs: &'a mut SubstitutionTable,
6747 input: IndexStr<'b>,
6748 ) -> Result<(Initializer, IndexStr<'b>)> {
6749 try_begin_parse!("Initializer", ctx, input);
6750
6751 let tail = consume(b"pi", input)?;
6752 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
6753 let tail = consume(b"E", tail)?;
6754 Ok((Initializer(exprs), tail))
6755 }
6756 }
6757
6758 impl<'subs, W> Demangle<'subs, W> for Initializer
6759 where
6760 W: 'subs + DemangleWrite,
6761 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6762 fn demangle<'prev, 'ctx>(
6763 &'subs self,
6764 ctx: &'ctx mut DemangleContext<'subs, W>,
6765 scope: Option<ArgScopeStack<'prev, 'subs>>,
6766 ) -> fmt::Result {
6767 let ctx = try_begin_demangle!(self, ctx, scope);
6768
6769 write!(ctx, "(")?;
6770 let mut need_comma = false;
6771 for expr in &self.0 {
6772 if need_comma {
6773 write!(ctx, ", ")?;
6774 }
6775 expr.demangle(ctx, scope)?;
6776 need_comma = true;
6777 }
6778 write!(ctx, ")")?;
6779 Ok(())
6780 }
6781 }
6782
6783 /// The `<local-name>` production.
6784 ///
6785 /// ```text
6786 /// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
6787 /// := Z <function encoding> E s [<discriminator>]
6788 /// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
6789 /// ```
6790 #[derive(Clone, Debug, PartialEq, Eq)]
6791 pub enum LocalName {
6792 /// The mangling of the enclosing function, the mangling of the entity
6793 /// relative to the function, and an optional discriminator.
6794 Relative(Box<Encoding>, Option<Box<Name>>, Option<Discriminator>),
6795
6796 /// A default argument in a class definition.
6797 Default(Box<Encoding>, Option<usize>, Box<Name>),
6798 }
6799
6800 impl Parse for LocalName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(LocalName, IndexStr<'b>)>6801 fn parse<'a, 'b>(
6802 ctx: &'a ParseContext,
6803 subs: &'a mut SubstitutionTable,
6804 input: IndexStr<'b>,
6805 ) -> Result<(LocalName, IndexStr<'b>)> {
6806 try_begin_parse!("LocalName", ctx, input);
6807
6808 let tail = consume(b"Z", input)?;
6809 let (encoding, tail) = Encoding::parse(ctx, subs, tail)?;
6810 let tail = consume(b"E", tail)?;
6811
6812 if let Ok(tail) = consume(b"s", tail) {
6813 let (disc, tail) = if let Ok((disc, tail)) = Discriminator::parse(ctx, subs, tail) {
6814 (Some(disc), tail)
6815 } else {
6816 (None, tail)
6817 };
6818 return Ok((LocalName::Relative(Box::new(encoding), None, disc), tail));
6819 }
6820
6821 if let Ok(tail) = consume(b"d", tail) {
6822 let (param, tail) = if let Ok((num, tail)) = Number::parse(ctx, subs, tail) {
6823 (Some(num as _), tail)
6824 } else {
6825 (None, tail)
6826 };
6827 let tail = consume(b"_", tail)?;
6828 let (name, tail) = Name::parse(ctx, subs, tail)?;
6829 return Ok((
6830 LocalName::Default(Box::new(encoding), param, Box::new(name)),
6831 tail,
6832 ));
6833 }
6834
6835 let (name, tail) = Name::parse(ctx, subs, tail)?;
6836 let (disc, tail) = if let Ok((disc, tail)) = Discriminator::parse(ctx, subs, tail) {
6837 (Some(disc), tail)
6838 } else {
6839 (None, tail)
6840 };
6841
6842 Ok((
6843 LocalName::Relative(Box::new(encoding), Some(Box::new(name)), disc),
6844 tail,
6845 ))
6846 }
6847 }
6848
6849 impl<'subs, W> Demangle<'subs, W> for LocalName
6850 where
6851 W: 'subs + DemangleWrite,
6852 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6853 fn demangle<'prev, 'ctx>(
6854 &'subs self,
6855 ctx: &'ctx mut DemangleContext<'subs, W>,
6856 scope: Option<ArgScopeStack<'prev, 'subs>>,
6857 ) -> fmt::Result {
6858 let ctx = try_begin_demangle!(self, ctx, scope);
6859
6860 let saved_show_params = ctx.show_params;
6861 ctx.show_params = true;
6862 let ret = match *self {
6863 LocalName::Relative(ref encoding, Some(ref name), _) => {
6864 encoding.demangle(ctx, scope)?;
6865 write!(ctx, "::")?;
6866 name.demangle(ctx, scope)
6867 }
6868 LocalName::Relative(ref encoding, None, _) => {
6869 // No name means that this is the symbol for a string literal.
6870 encoding.demangle(ctx, scope)?;
6871 write!(ctx, "::string literal")?;
6872 Ok(())
6873 }
6874 LocalName::Default(ref encoding, _, _) => encoding.demangle(ctx, scope),
6875 };
6876 ctx.show_params = saved_show_params;
6877 ret
6878 }
6879 }
6880
6881 impl GetTemplateArgs for LocalName {
get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>6882 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
6883 match *self {
6884 LocalName::Relative(_, None, _) => None,
6885 LocalName::Relative(_, Some(ref name), _) | LocalName::Default(_, _, ref name) => {
6886 name.get_template_args(subs)
6887 }
6888 }
6889 }
6890 }
6891
6892 impl<'a> GetLeafName<'a> for LocalName {
get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>6893 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
6894 match *self {
6895 LocalName::Relative(_, None, _) => None,
6896 LocalName::Relative(_, Some(ref name), _) | LocalName::Default(_, _, ref name) => {
6897 name.get_leaf_name(subs)
6898 }
6899 }
6900 }
6901 }
6902
6903 /// The `<discriminator>` production.
6904 ///
6905 /// ```text
6906 /// <discriminator> := _ <non-negative number> # when number < 10
6907 /// := __ <non-negative number> _ # when number >= 10
6908 /// ```
6909 #[derive(Clone, Debug, PartialEq, Eq)]
6910 pub struct Discriminator(usize);
6911
6912 impl Parse for Discriminator {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Discriminator, IndexStr<'b>)>6913 fn parse<'a, 'b>(
6914 ctx: &'a ParseContext,
6915 _subs: &'a mut SubstitutionTable,
6916 input: IndexStr<'b>,
6917 ) -> Result<(Discriminator, IndexStr<'b>)> {
6918 try_begin_parse!("Discriminator", ctx, input);
6919
6920 let tail = consume(b"_", input)?;
6921
6922 if let Ok(tail) = consume(b"_", tail) {
6923 let (num, tail) = parse_number(10, false, tail)?;
6924 debug_assert!(num >= 0);
6925 if num < 10 {
6926 return Err(error::Error::UnexpectedText);
6927 }
6928 let tail = consume(b"_", tail)?;
6929 return Ok((Discriminator(num as _), tail));
6930 }
6931
6932 match tail.try_split_at(1) {
6933 None => Err(error::Error::UnexpectedEnd),
6934 Some((head, tail)) => match head.as_ref()[0] {
6935 b'0' => Ok((Discriminator(0), tail)),
6936 b'1' => Ok((Discriminator(1), tail)),
6937 b'2' => Ok((Discriminator(2), tail)),
6938 b'3' => Ok((Discriminator(3), tail)),
6939 b'4' => Ok((Discriminator(4), tail)),
6940 b'5' => Ok((Discriminator(5), tail)),
6941 b'6' => Ok((Discriminator(6), tail)),
6942 b'7' => Ok((Discriminator(7), tail)),
6943 b'8' => Ok((Discriminator(8), tail)),
6944 b'9' => Ok((Discriminator(9), tail)),
6945 _ => Err(error::Error::UnexpectedText),
6946 },
6947 }
6948 }
6949 }
6950
6951 /// The `<closure-type-name>` production.
6952 ///
6953 /// ```text
6954 /// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
6955 /// ```
6956 #[derive(Clone, Debug, PartialEq, Eq)]
6957 pub struct ClosureTypeName(LambdaSig, Option<usize>);
6958
6959 impl Parse for ClosureTypeName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(ClosureTypeName, IndexStr<'b>)>6960 fn parse<'a, 'b>(
6961 ctx: &'a ParseContext,
6962 subs: &'a mut SubstitutionTable,
6963 input: IndexStr<'b>,
6964 ) -> Result<(ClosureTypeName, IndexStr<'b>)> {
6965 try_begin_parse!("ClosureTypeName", ctx, input);
6966
6967 let tail = consume(b"Ul", input)?;
6968 let (sig, tail) = LambdaSig::parse(ctx, subs, tail)?;
6969 let tail = consume(b"E", tail)?;
6970 let (num, tail) = if let Ok((num, tail)) = parse_number(10, false, tail) {
6971 (Some(num as _), tail)
6972 } else {
6973 (None, tail)
6974 };
6975 let tail = consume(b"_", tail)?;
6976 Ok((ClosureTypeName(sig, num), tail))
6977 }
6978 }
6979
6980 impl<'subs, W> Demangle<'subs, W> for ClosureTypeName
6981 where
6982 W: 'subs + DemangleWrite,
6983 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result6984 fn demangle<'prev, 'ctx>(
6985 &'subs self,
6986 ctx: &'ctx mut DemangleContext<'subs, W>,
6987 scope: Option<ArgScopeStack<'prev, 'subs>>,
6988 ) -> fmt::Result {
6989 let ctx = try_begin_demangle!(self, ctx, scope);
6990
6991 write!(ctx, "{{lambda(")?;
6992 self.0.demangle(ctx, scope)?;
6993 write!(ctx, ")#{}}}", self.1.map_or(1, |n| n + 2))?;
6994 Ok(())
6995 }
6996 }
6997
6998 impl<'subs> ArgScope<'subs, 'subs> for ClosureTypeName {
leaf_name(&'subs self) -> Result<LeafName<'subs>>6999 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
7000 Ok(LeafName::Closure(self))
7001 }
7002
get_template_arg( &'subs self, _: usize, ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)>7003 fn get_template_arg(
7004 &'subs self,
7005 _: usize,
7006 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
7007 Err(error::Error::BadTemplateArgReference)
7008 }
7009
get_function_arg(&'subs self, _: usize) -> Result<&'subs Type>7010 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
7011 Err(error::Error::BadFunctionArgReference)
7012 }
7013 }
7014
7015 impl<'a> GetLeafName<'a> for ClosureTypeName {
7016 #[inline]
get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>>7017 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7018 Some(LeafName::Closure(self))
7019 }
7020 }
7021
7022 impl ClosureTypeName {
7023 #[inline]
starts_with(byte: u8, input: &IndexStr) -> bool7024 fn starts_with(byte: u8, input: &IndexStr) -> bool {
7025 byte == b'U' && input.peek_second().map(|b| b == b'l').unwrap_or(false)
7026 }
7027 }
7028
7029 /// The `<lambda-sig>` production.
7030 ///
7031 /// ```text
7032 /// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
7033 /// ```
7034 #[derive(Clone, Debug, PartialEq, Eq)]
7035 pub struct LambdaSig(Vec<TypeHandle>);
7036
7037 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 + DemangleWrite,7038 fn demangle_args<'subs, 'prev, 'ctx, W>(
7039 &'subs self,
7040 ctx: &'ctx mut DemangleContext<'subs, W>,
7041 scope: Option<ArgScopeStack<'prev, 'subs>>,
7042 ) -> fmt::Result
7043 where
7044 W: 'subs + DemangleWrite,
7045 {
7046 let mut need_comma = false;
7047 for ty in &self.0 {
7048 if need_comma {
7049 write!(ctx, ", ")?;
7050 }
7051 ty.demangle(ctx, scope)?;
7052 need_comma = true;
7053 }
7054 Ok(())
7055 }
7056 }
7057
7058 impl Parse for LambdaSig {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(LambdaSig, IndexStr<'b>)>7059 fn parse<'a, 'b>(
7060 ctx: &'a ParseContext,
7061 subs: &'a mut SubstitutionTable,
7062 input: IndexStr<'b>,
7063 ) -> Result<(LambdaSig, IndexStr<'b>)> {
7064 try_begin_parse!("LambdaSig", ctx, input);
7065
7066 let (types, tail) = if let Ok(tail) = consume(b"v", input) {
7067 (vec![], tail)
7068 } else {
7069 one_or_more::<TypeHandle>(ctx, subs, input)?
7070 };
7071 Ok((LambdaSig(types), tail))
7072 }
7073 }
7074
7075 impl<'subs, W> Demangle<'subs, W> for LambdaSig
7076 where
7077 W: 'subs + DemangleWrite,
7078 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result7079 fn demangle<'prev, 'ctx>(
7080 &'subs self,
7081 ctx: &'ctx mut DemangleContext<'subs, W>,
7082 scope: Option<ArgScopeStack<'prev, 'subs>>,
7083 ) -> fmt::Result {
7084 let ctx = try_begin_demangle!(self, ctx, scope);
7085
7086 ctx.is_lambda_arg = true;
7087 let r = self.demangle_args(ctx, scope);
7088 ctx.is_lambda_arg = false;
7089 r
7090 }
7091 }
7092
7093 /// The `<data-member-prefix>` production.
7094 ///
7095 /// ```text
7096 /// <data-member-prefix> := <member source-name> M
7097 /// ```
7098 #[derive(Clone, Debug, PartialEq, Eq)]
7099 pub struct DataMemberPrefix(SourceName);
7100
7101 impl Parse for DataMemberPrefix {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(DataMemberPrefix, IndexStr<'b>)>7102 fn parse<'a, 'b>(
7103 ctx: &'a ParseContext,
7104 subs: &'a mut SubstitutionTable,
7105 input: IndexStr<'b>,
7106 ) -> Result<(DataMemberPrefix, IndexStr<'b>)> {
7107 try_begin_parse!("DataMemberPrefix", ctx, input);
7108
7109 let (name, tail) = SourceName::parse(ctx, subs, input)?;
7110 let tail = consume(b"M", tail)?;
7111 Ok((DataMemberPrefix(name), tail))
7112 }
7113 }
7114
7115 impl<'a> GetLeafName<'a> for DataMemberPrefix {
7116 #[inline]
get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>>7117 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7118 Some(LeafName::SourceName(&self.0))
7119 }
7120 }
7121
7122 impl DataMemberPrefix {
starts_with(byte: u8) -> bool7123 fn starts_with(byte: u8) -> bool {
7124 SourceName::starts_with(byte)
7125 }
7126 }
7127
7128 impl<'subs, W> Demangle<'subs, W> for DataMemberPrefix
7129 where
7130 W: 'subs + DemangleWrite,
7131 {
7132 #[inline]
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result7133 fn demangle<'prev, 'ctx>(
7134 &'subs self,
7135 ctx: &'ctx mut DemangleContext<'subs, W>,
7136 scope: Option<ArgScopeStack<'prev, 'subs>>,
7137 ) -> fmt::Result {
7138 let ctx = try_begin_demangle!(self, ctx, scope);
7139
7140 ctx.push_demangle_node(DemangleNodeType::DataMemberPrefix);
7141 let ret = self.0.demangle(ctx, scope);
7142 ctx.pop_demangle_node();
7143 ret
7144 }
7145 }
7146
7147 /// The `<substitution>` form: a back-reference to some component we've already
7148 /// parsed.
7149 ///
7150 /// ```text
7151 /// <substitution> ::= S <seq-id> _
7152 /// ::= S_
7153 /// ::= St # ::std::
7154 /// ::= Sa # ::std::allocator
7155 /// ::= Sb # ::std::basic_string
7156 /// ::= Ss # ::std::basic_string < char,
7157 /// ::std::char_traits<char>,
7158 /// ::std::allocator<char> >
7159 /// ::= Si # ::std::basic_istream<char, std::char_traits<char> >
7160 /// ::= So # ::std::basic_ostream<char, std::char_traits<char> >
7161 /// ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
7162 /// ```
7163 #[derive(Clone, Debug, PartialEq, Eq)]
7164 pub enum Substitution {
7165 /// A reference to an entity that already occurred, ie the `S_` and `S
7166 /// <seq-id> _` forms.
7167 BackReference(usize),
7168
7169 /// A well-known substitution component. These are the components that do
7170 /// not appear in the substitution table, but have abbreviations specified
7171 /// directly in the grammar.
7172 WellKnown(WellKnownComponent),
7173 }
7174
7175 impl Parse for Substitution {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Substitution, IndexStr<'b>)>7176 fn parse<'a, 'b>(
7177 ctx: &'a ParseContext,
7178 subs: &'a mut SubstitutionTable,
7179 input: IndexStr<'b>,
7180 ) -> Result<(Substitution, IndexStr<'b>)> {
7181 try_begin_parse!("Substitution", ctx, input);
7182
7183 if let Ok((well_known, tail)) = WellKnownComponent::parse(ctx, subs, input) {
7184 return Ok((Substitution::WellKnown(well_known), tail));
7185 }
7186
7187 let tail = consume(b"S", input)?;
7188 let (idx, tail) = if let Ok((idx, tail)) = SeqId::parse(ctx, subs, tail) {
7189 (idx.0 + 1, tail)
7190 } else {
7191 (0, tail)
7192 };
7193
7194 if !subs.contains(idx) {
7195 return Err(error::Error::BadBackReference);
7196 }
7197
7198 let tail = consume(b"_", tail)?;
7199 log!("Found a reference to @ {}", idx);
7200 Ok((Substitution::BackReference(idx), tail))
7201 }
7202 }
7203
7204 define_vocabulary! {
7205 /// The `<substitution>` variants that are encoded directly in the grammar,
7206 /// rather than as back references to other components in the substitution
7207 /// table.
7208 #[derive(Clone, Debug, PartialEq, Eq)]
7209 pub enum WellKnownComponent {
7210 Std (b"St", "std"),
7211 StdAllocator (b"Sa", "std::allocator"),
7212 StdString1 (b"Sb", "std::basic_string"),
7213 StdString2 (b"Ss", "std::string"),
7214 StdIstream (b"Si", "std::basic_istream<char, std::char_traits<char> >"),
7215 StdOstream (b"So", "std::ostream"),
7216 StdIostream (b"Sd", "std::basic_iostream<char, std::char_traits<char> >")
7217 }
7218 }
7219
7220 impl<'a> GetLeafName<'a> for WellKnownComponent {
get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>>7221 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7222 match *self {
7223 WellKnownComponent::Std => None,
7224 _ => Some(LeafName::WellKnownComponent(self)),
7225 }
7226 }
7227 }
7228
7229 impl<'a> ArgScope<'a, 'a> for WellKnownComponent {
leaf_name(&'a self) -> Result<LeafName<'a>>7230 fn leaf_name(&'a self) -> Result<LeafName<'a>> {
7231 Ok(LeafName::WellKnownComponent(self))
7232 }
7233
get_template_arg(&'a self, _: usize) -> Result<(&'a TemplateArg, &'a TemplateArgs)>7234 fn get_template_arg(&'a self, _: usize) -> Result<(&'a TemplateArg, &'a TemplateArgs)> {
7235 Err(error::Error::BadTemplateArgReference)
7236 }
7237
get_function_arg(&'a self, _: usize) -> Result<&'a Type>7238 fn get_function_arg(&'a self, _: usize) -> Result<&'a Type> {
7239 Err(error::Error::BadFunctionArgReference)
7240 }
7241 }
7242
7243 impl<'subs, W> DemangleAsLeaf<'subs, W> for WellKnownComponent
7244 where
7245 W: 'subs + DemangleWrite,
7246 {
demangle_as_leaf<'me, 'ctx>( &'me self, ctx: &'ctx mut DemangleContext<'subs, W>, ) -> fmt::Result7247 fn demangle_as_leaf<'me, 'ctx>(
7248 &'me self,
7249 ctx: &'ctx mut DemangleContext<'subs, W>,
7250 ) -> fmt::Result {
7251 match *self {
7252 WellKnownComponent::Std => {
7253 panic!("should never treat `WellKnownComponent::Std` as a leaf name")
7254 }
7255 WellKnownComponent::StdAllocator => write!(ctx, "allocator"),
7256 WellKnownComponent::StdString1 => write!(ctx, "basic_string"),
7257 WellKnownComponent::StdString2 => write!(ctx, "string"),
7258 WellKnownComponent::StdIstream => write!(ctx, "basic_istream"),
7259 WellKnownComponent::StdOstream => write!(ctx, "ostream"),
7260 WellKnownComponent::StdIostream => write!(ctx, "basic_iostream"),
7261 }
7262 }
7263 }
7264
7265 /// The `<special-name>` production.
7266 ///
7267 /// The `<special-name>` production is spread in pieces through out the ABI
7268 /// spec, and then there are a bunch of `g++` extensions that have become de
7269 /// facto.
7270 ///
7271 /// ### 5.1.4.1 Virtual Tables and RTTI
7272 ///
7273 /// ```text
7274 /// <special-name> ::= TV <type> # virtual table
7275 /// ::= TT <type> # VTT structure (construction vtable index)
7276 /// ::= TI <type> # typeinfo structure
7277 /// ::= TS <type> # typeinfo name (null-terminated byte string)
7278 /// ```
7279 ///
7280 /// ### 5.1.4.2 Virtual Override Thunks
7281 ///
7282 /// ```text
7283 /// <special-name> ::= T <call-offset> <base encoding>
7284 /// # base is the nominal target function of thunk
7285 ///
7286 /// <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
7287 /// # base is the nominal target function of thunk
7288 /// # first call-offset is 'this' adjustment
7289 /// # second call-offset is result adjustment
7290 /// ```
7291 ///
7292 /// ### 5.1.4.4 Guard Variables
7293 ///
7294 /// ```text
7295 /// <special-name> ::= GV <object name> # Guard variable for one-time initialization
7296 /// # No <type>
7297 /// ```
7298 ///
7299 /// ### 5.1.4.5 Lifetime-Extended Temporaries
7300 ///
7301 /// ```text
7302 /// <special-name> ::= GR <object name> _ # First temporary
7303 /// <special-name> ::= GR <object name> <seq-id> _ # Subsequent temporaries
7304 /// ```
7305 ///
7306 /// ### De Facto Standard Extensions
7307 ///
7308 /// ```text
7309 /// <special-name> ::= TC <type> <number> _ <type> # construction vtable
7310 /// ::= TF <type> # typinfo function
7311 /// ::= TH <name> # TLS initialization function
7312 /// ::= TW <name> # TLS wrapper function
7313 /// ::= Gr <resource name> # Java Resource
7314 /// ::= GTt <encoding> # Transaction-Safe function
7315 /// ::= GTn <encoding> # Non-Transaction-Safe function
7316 /// ```
7317 #[derive(Clone, Debug, PartialEq, Eq)]
7318 pub enum SpecialName {
7319 /// A virtual table.
7320 VirtualTable(TypeHandle),
7321
7322 /// A VTT structure (construction vtable index).
7323 Vtt(TypeHandle),
7324
7325 /// A typeinfo structure.
7326 Typeinfo(TypeHandle),
7327
7328 /// A typeinfo name (null-terminated byte string).
7329 TypeinfoName(TypeHandle),
7330
7331 /// A virtual override thunk.
7332 VirtualOverrideThunk(CallOffset, Box<Encoding>),
7333
7334 /// A virtual override thunk with a covariant return type.
7335 VirtualOverrideThunkCovariant(CallOffset, CallOffset, Box<Encoding>),
7336
7337 /// An initialization guard for some static storage.
7338 Guard(Name),
7339
7340 /// A temporary used in the initialization of a static storage and promoted
7341 /// to a static lifetime.
7342 GuardTemporary(Name, usize),
7343
7344 /// A construction vtable structure.
7345 ConstructionVtable(TypeHandle, usize, TypeHandle),
7346
7347 /// A typeinfo function.
7348 TypeinfoFunction(TypeHandle),
7349
7350 /// A TLS initialization function.
7351 TlsInit(Name),
7352
7353 /// A TLS wrapper function.
7354 TlsWrapper(Name),
7355
7356 /// A Java Resource.
7357 JavaResource(Vec<ResourceName>),
7358
7359 /// A function declared transaction-safe
7360 TransactionClone(Box<Encoding>),
7361
7362 /// A function declared non-transaction-safe
7363 NonTransactionClone(Box<Encoding>),
7364 }
7365
7366 impl Parse for SpecialName {
parse<'a, 'b>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(SpecialName, IndexStr<'b>)>7367 fn parse<'a, 'b>(
7368 ctx: &'a ParseContext,
7369 subs: &'a mut SubstitutionTable,
7370 input: IndexStr<'b>,
7371 ) -> Result<(SpecialName, IndexStr<'b>)> {
7372 try_begin_parse!("SpecialName", ctx, input);
7373
7374 let (head, tail) = match input.try_split_at(2) {
7375 None => return Err(error::Error::UnexpectedEnd),
7376 Some((head, tail)) => (head, tail),
7377 };
7378
7379 match head.as_ref() {
7380 b"TV" => {
7381 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7382 Ok((SpecialName::VirtualTable(ty), tail))
7383 }
7384 b"TT" => {
7385 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7386 Ok((SpecialName::Vtt(ty), tail))
7387 }
7388 b"TI" => {
7389 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7390 Ok((SpecialName::Typeinfo(ty), tail))
7391 }
7392 b"TS" => {
7393 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7394 Ok((SpecialName::TypeinfoName(ty), tail))
7395 }
7396 b"Tc" => {
7397 let (first, tail) = CallOffset::parse(ctx, subs, tail)?;
7398 let (second, tail) = CallOffset::parse(ctx, subs, tail)?;
7399 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7400 Ok((
7401 SpecialName::VirtualOverrideThunkCovariant(first, second, Box::new(base)),
7402 tail,
7403 ))
7404 }
7405 b"Th" | b"Tv" => {
7406 // The "h"/"v" is part of the `<call-offset>`, so back up to the
7407 // `input`.
7408 let tail = consume(b"T", input).unwrap();
7409 let (offset, tail) = CallOffset::parse(ctx, subs, tail)?;
7410 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7411 Ok((
7412 SpecialName::VirtualOverrideThunk(offset, Box::new(base)),
7413 tail,
7414 ))
7415 }
7416 b"TC" => {
7417 let (ty1, tail) = TypeHandle::parse(ctx, subs, tail)?;
7418 let (n, tail) = parse_number(10, false, tail)?;
7419 let tail = consume(b"_", tail)?;
7420 let (ty2, tail) = TypeHandle::parse(ctx, subs, tail)?;
7421 Ok((SpecialName::ConstructionVtable(ty1, n as usize, ty2), tail))
7422 }
7423 b"TF" => {
7424 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7425 Ok((SpecialName::TypeinfoFunction(ty), tail))
7426 }
7427 b"TH" => {
7428 let (name, tail) = Name::parse(ctx, subs, tail)?;
7429 Ok((SpecialName::TlsInit(name), tail))
7430 }
7431 b"TW" => {
7432 let (name, tail) = Name::parse(ctx, subs, tail)?;
7433 Ok((SpecialName::TlsWrapper(name), tail))
7434 }
7435 b"GV" => {
7436 let (name, tail) = Name::parse(ctx, subs, tail)?;
7437 Ok((SpecialName::Guard(name), tail))
7438 }
7439 b"GR" => {
7440 let (name, tail) = Name::parse(ctx, subs, tail)?;
7441 let (idx, tail) = if let Ok(tail) = consume(b"_", tail) {
7442 (0, tail)
7443 } else {
7444 let (idx, tail) = SeqId::parse(ctx, subs, tail)?;
7445 let tail = consume(b"_", tail)?;
7446 (idx.0 + 1, tail)
7447 };
7448 Ok((SpecialName::GuardTemporary(name, idx), tail))
7449 }
7450 b"Gr" => {
7451 let (resource_name_len, tail) = parse_number(10, false, tail)?;
7452 if resource_name_len == 0 {
7453 return Err(error::Error::UnexpectedText);
7454 }
7455
7456 let (head, tail) = match tail.try_split_at(resource_name_len as _) {
7457 Some((head, tail)) => (head, tail),
7458 None => return Err(error::Error::UnexpectedEnd),
7459 };
7460
7461 let head = consume(b"_", head)?;
7462
7463 let (resource_names, empty) = zero_or_more::<ResourceName>(ctx, subs, head)?;
7464 if !empty.is_empty() {
7465 return Err(error::Error::UnexpectedText);
7466 }
7467
7468 Ok((SpecialName::JavaResource(resource_names), tail))
7469 }
7470 b"GT" => {
7471 match tail.next_or(error::Error::UnexpectedEnd)? {
7472 (b'n', tail) => {
7473 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7474 Ok((SpecialName::NonTransactionClone(Box::new(base)), tail))
7475 }
7476 // Different letters could stand for different types of
7477 // transactional cloning, but for now, treat them all the same
7478 (b't', tail) | (_, tail) => {
7479 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7480 Ok((SpecialName::TransactionClone(Box::new(base)), tail))
7481 }
7482 }
7483 }
7484 _ => Err(error::Error::UnexpectedText),
7485 }
7486 }
7487 }
7488
7489 impl<'subs, W> Demangle<'subs, W> for SpecialName
7490 where
7491 W: 'subs + DemangleWrite,
7492 {
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result7493 fn demangle<'prev, 'ctx>(
7494 &'subs self,
7495 ctx: &'ctx mut DemangleContext<'subs, W>,
7496 scope: Option<ArgScopeStack<'prev, 'subs>>,
7497 ) -> fmt::Result {
7498 let ctx = try_begin_demangle!(self, ctx, scope);
7499
7500 match *self {
7501 SpecialName::VirtualTable(ref ty) => {
7502 write!(ctx, "{{vtable(")?;
7503 ctx.push_demangle_node(DemangleNodeType::VirtualTable);
7504 ty.demangle(ctx, scope)?;
7505 ctx.pop_demangle_node();
7506 write!(ctx, ")}}")?;
7507 Ok(())
7508 }
7509 SpecialName::Vtt(ref ty) => {
7510 write!(ctx, "{{vtt(")?;
7511 ty.demangle(ctx, scope)?;
7512 write!(ctx, ")}}")?;
7513 Ok(())
7514 }
7515 SpecialName::Typeinfo(ref ty) => {
7516 write!(ctx, "typeinfo for ")?;
7517 ty.demangle(ctx, scope)
7518 }
7519 SpecialName::TypeinfoName(ref ty) => {
7520 write!(ctx, "typeinfo name for ")?;
7521 ty.demangle(ctx, scope)
7522 }
7523 SpecialName::VirtualOverrideThunk(ref offset, ref encoding) => {
7524 write!(ctx, "{{virtual override thunk(")?;
7525 offset.demangle(ctx, scope)?;
7526 write!(ctx, ", ")?;
7527 encoding.demangle(ctx, scope)?;
7528 write!(ctx, ")}}")?;
7529 Ok(())
7530 }
7531 SpecialName::VirtualOverrideThunkCovariant(
7532 ref this_offset,
7533 ref result_offset,
7534 ref encoding,
7535 ) => {
7536 write!(ctx, "{{virtual override thunk(")?;
7537 this_offset.demangle(ctx, scope)?;
7538 write!(ctx, ", ")?;
7539 result_offset.demangle(ctx, scope)?;
7540 write!(ctx, ", ")?;
7541 encoding.demangle(ctx, scope)?;
7542 write!(ctx, ")}}")?;
7543 Ok(())
7544 }
7545 SpecialName::Guard(ref name) => {
7546 write!(ctx, "guard variable for ")?;
7547 name.demangle(ctx, scope)
7548 }
7549 SpecialName::GuardTemporary(ref name, n) => {
7550 write!(ctx, "reference temporary #{} for ", n)?;
7551 name.demangle(ctx, scope)
7552 }
7553 SpecialName::ConstructionVtable(ref ty1, _, ref ty2) => {
7554 write!(ctx, "construction vtable for ")?;
7555 ty1.demangle(ctx, scope)?;
7556 write!(ctx, "-in-")?;
7557 ty2.demangle(ctx, scope)
7558 }
7559 SpecialName::TypeinfoFunction(ref ty) => {
7560 write!(ctx, "typeinfo fn for ")?;
7561 ty.demangle(ctx, scope)
7562 }
7563 SpecialName::TlsInit(ref name) => {
7564 write!(ctx, "TLS init function for ")?;
7565 name.demangle(ctx, scope)
7566 }
7567 SpecialName::TlsWrapper(ref name) => {
7568 write!(ctx, "TLS wrapper function for ")?;
7569 name.demangle(ctx, scope)
7570 }
7571 SpecialName::TransactionClone(ref encoding) => {
7572 write!(ctx, "transaction clone for ")?;
7573 encoding.demangle(ctx, scope)
7574 }
7575 SpecialName::NonTransactionClone(ref encoding) => {
7576 write!(ctx, "non-transaction clone for ")?;
7577 encoding.demangle(ctx, scope)
7578 }
7579 SpecialName::JavaResource(ref names) => {
7580 write!(ctx, "java resource ")?;
7581 for name in names {
7582 name.demangle(ctx, scope)?;
7583 }
7584 Ok(())
7585 }
7586 }
7587 }
7588 }
7589
7590 /// The `<resource name>` pseudo-terminal.
7591 #[derive(Clone, Debug, PartialEq, Eq)]
7592 pub struct ResourceName {
7593 start: usize,
7594 end: usize,
7595 }
7596
7597 impl Parse for ResourceName {
parse<'a, 'b>( ctx: &'a ParseContext, _subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(ResourceName, IndexStr<'b>)>7598 fn parse<'a, 'b>(
7599 ctx: &'a ParseContext,
7600 _subs: &'a mut SubstitutionTable,
7601 input: IndexStr<'b>,
7602 ) -> Result<(ResourceName, IndexStr<'b>)> {
7603 try_begin_parse!("ResourceName", ctx, input);
7604
7605 if input.is_empty() {
7606 return Err(error::Error::UnexpectedEnd);
7607 }
7608
7609 let mut end = input
7610 .as_ref()
7611 .iter()
7612 .map(|&c| c as char)
7613 .take_while(|&c| c != '$' || c.is_digit(36))
7614 .count();
7615
7616 if end == 0 {
7617 return Err(error::Error::UnexpectedText);
7618 }
7619
7620 if input.range_from(end..).peek() == Some(b'$') {
7621 match input.range_from(end..).peek_second() {
7622 Some(b'S') | Some(b'_') | Some(b'$') => end += 2,
7623 _ => return Err(error::Error::UnexpectedText),
7624 }
7625 }
7626
7627 let tail = input.range_from(end..);
7628
7629 let resource_name = ResourceName {
7630 start: input.index(),
7631 end: tail.index(),
7632 };
7633
7634 Ok((resource_name, tail))
7635 }
7636 }
7637
7638 impl<'subs, W> Demangle<'subs, W> for ResourceName
7639 where
7640 W: 'subs + DemangleWrite,
7641 {
7642 #[inline]
demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut DemangleContext<'subs, W>, scope: Option<ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result7643 fn demangle<'prev, 'ctx>(
7644 &'subs self,
7645 ctx: &'ctx mut DemangleContext<'subs, W>,
7646 scope: Option<ArgScopeStack<'prev, 'subs>>,
7647 ) -> fmt::Result {
7648 let ctx = try_begin_demangle!(self, ctx, scope);
7649
7650 let mut i = self.start;
7651 while i < self.end {
7652 let ch = ctx.input[i];
7653 if ch == b'$' {
7654 // Skip past the '$'
7655 i += 1;
7656 match ctx.input[i] {
7657 b'S' => write!(ctx, "{}", '/')?,
7658 b'_' => write!(ctx, "{}", '.')?,
7659 b'$' => write!(ctx, "{}", '$')?,
7660 _ => {
7661 // Fall through
7662 }
7663 }
7664 } else {
7665 write!(ctx, "{}", ch as char)?;
7666 }
7667 i += 1;
7668 }
7669
7670 Ok(())
7671 }
7672 }
7673 /// Expect and consume the given byte str, and return the advanced `IndexStr` if
7674 /// we saw the expectation. Otherwise return an error of kind
7675 /// `error::Error::UnexpectedText` if the input doesn't match, or
7676 /// `error::Error::UnexpectedEnd` if it isn't long enough.
7677 #[inline]
consume<'a>(expected: &[u8], input: IndexStr<'a>) -> Result<IndexStr<'a>>7678 fn consume<'a>(expected: &[u8], input: IndexStr<'a>) -> Result<IndexStr<'a>> {
7679 match input.try_split_at(expected.len()) {
7680 Some((head, tail)) if head == expected => Ok(tail),
7681 Some(_) => Err(error::Error::UnexpectedText),
7682 None => Err(error::Error::UnexpectedEnd),
7683 }
7684 }
7685
one_or_more<'a, 'b, P>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Vec<P>, IndexStr<'b>)> where P: Parse,7686 fn one_or_more<'a, 'b, P>(
7687 ctx: &'a ParseContext,
7688 subs: &'a mut SubstitutionTable,
7689 input: IndexStr<'b>,
7690 ) -> Result<(Vec<P>, IndexStr<'b>)>
7691 where
7692 P: Parse,
7693 {
7694 let (first, mut tail) = P::parse(ctx, subs, input)?;
7695 let mut results = vec![first];
7696 loop {
7697 if let Ok((parsed, tail_tail)) = P::parse(ctx, subs, tail) {
7698 results.push(parsed);
7699 tail = tail_tail;
7700 } else {
7701 return Ok((results, tail));
7702 }
7703 }
7704 }
7705
zero_or_more<'a, 'b, P>( ctx: &'a ParseContext, subs: &'a mut SubstitutionTable, input: IndexStr<'b>, ) -> Result<(Vec<P>, IndexStr<'b>)> where P: Parse,7706 fn zero_or_more<'a, 'b, P>(
7707 ctx: &'a ParseContext,
7708 subs: &'a mut SubstitutionTable,
7709 input: IndexStr<'b>,
7710 ) -> Result<(Vec<P>, IndexStr<'b>)>
7711 where
7712 P: Parse,
7713 {
7714 let mut tail = input;
7715 let mut results = vec![];
7716 loop {
7717 if let Ok((parsed, tail_tail)) = P::parse(ctx, subs, tail) {
7718 results.push(parsed);
7719 tail = tail_tail;
7720 } else {
7721 return Ok((results, tail));
7722 }
7723 }
7724 }
7725
7726 /// Parse a number with the given `base`. Do not allow negative numbers
7727 /// (prefixed with an 'n' instead of a '-') if `allow_signed` is false.
7728 #[allow(unsafe_code)]
parse_number(base: u32, allow_signed: bool, mut input: IndexStr) -> Result<(isize, IndexStr)>7729 fn parse_number(base: u32, allow_signed: bool, mut input: IndexStr) -> Result<(isize, IndexStr)> {
7730 if input.is_empty() {
7731 return Err(error::Error::UnexpectedEnd);
7732 }
7733
7734 let num_is_negative = if allow_signed && input.as_ref()[0] == b'n' {
7735 input = input.range_from(1..);
7736
7737 if input.is_empty() {
7738 return Err(error::Error::UnexpectedEnd);
7739 }
7740
7741 true
7742 } else {
7743 false
7744 };
7745
7746 let num_numeric = input
7747 .as_ref()
7748 .iter()
7749 .map(|&c| c as char)
7750 .take_while(|c| c.is_digit(base) && (c.is_numeric() || c.is_uppercase()))
7751 .count();
7752 if num_numeric == 0 {
7753 return Err(error::Error::UnexpectedText);
7754 }
7755
7756 let (head, tail) = input.split_at(num_numeric);
7757 let head = head.as_ref();
7758
7759 if num_numeric > 1 && head[0] == b'0' {
7760 // "<number>s appearing in mangled names never have leading zeroes,
7761 // except for the value zero, represented as '0'."
7762 return Err(error::Error::UnexpectedText);
7763 }
7764
7765 let head = unsafe {
7766 // Safe because we know we only have valid numeric chars in this
7767 // slice, which are valid UTF-8.
7768 ::std::str::from_utf8_unchecked(head)
7769 };
7770
7771 let mut number = isize::from_str_radix(head, base).map_err(|_| error::Error::Overflow)?;
7772 if num_is_negative {
7773 number = -number;
7774 }
7775
7776 Ok((number, tail))
7777 }
7778
7779 #[cfg(test)]
7780 mod tests {
7781 use super::{
7782 ArrayType, BareFunctionType, BaseUnresolvedName, BuiltinType, CallOffset, ClassEnumType,
7783 ClosureTypeName, CtorDtorName, CvQualifiers, DataMemberPrefix, Decltype, DestructorName,
7784 Discriminator, Encoding, ExprPrimary, Expression, FunctionParam, FunctionType,
7785 GlobalCtorDtor, Identifier, Initializer, LambdaSig, LocalName, MangledName, MemberName,
7786 Name, NestedName, NonSubstitution, Number, NvOffset, OperatorName, Parse, ParseContext,
7787 PointerToMemberType, Prefix, PrefixHandle, RefQualifier, ResourceName, SeqId, SimpleId,
7788 SimpleOperatorName, SourceName, SpecialName, StandardBuiltinType, Substitution, TaggedName,
7789 TemplateArg, TemplateArgs, TemplateParam, TemplateTemplateParam,
7790 TemplateTemplateParamHandle, Type, TypeHandle, UnnamedTypeName, UnqualifiedName,
7791 UnresolvedName, UnresolvedQualifierLevel, UnresolvedType, UnresolvedTypeHandle,
7792 UnscopedName, UnscopedTemplateName, UnscopedTemplateNameHandle, VOffset, VectorType,
7793 WellKnownComponent,
7794 };
7795
7796 use boxed::Box;
7797 use error::Error;
7798 use index_str::IndexStr;
7799 use std::fmt::Debug;
7800 use std::iter::FromIterator;
7801 use string::String;
7802 use subs::{Substitutable, SubstitutionTable};
7803
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]>,7804 fn assert_parse_ok<P, S1, S2, I1, I2>(
7805 production: &'static str,
7806 subs: S1,
7807 input: I1,
7808 expected: P,
7809 expected_tail: I2,
7810 expected_new_subs: S2,
7811 ) where
7812 P: Debug + Parse + PartialEq,
7813 S1: AsRef<[Substitutable]>,
7814 S2: AsRef<[Substitutable]>,
7815 I1: AsRef<[u8]>,
7816 I2: AsRef<[u8]>,
7817 {
7818 let ctx = ParseContext::new(Default::default());
7819 let input = input.as_ref();
7820 let expected_tail = expected_tail.as_ref();
7821
7822 let expected_subs = SubstitutionTable::from_iter(
7823 subs.as_ref()
7824 .iter()
7825 .cloned()
7826 .chain(expected_new_subs.as_ref().iter().cloned()),
7827 );
7828 let mut subs = SubstitutionTable::from_iter(subs.as_ref().iter().cloned());
7829
7830 match P::parse(&ctx, &mut subs, IndexStr::from(input)) {
7831 Err(error) => panic!(
7832 "Parsing {:?} as {} failed: {}",
7833 String::from_utf8_lossy(input),
7834 production,
7835 error
7836 ),
7837 Ok((value, tail)) => {
7838 if value != expected {
7839 panic!(
7840 "Parsing {:?} as {} produced\n\n{:#?}\n\nbut we expected\n\n{:#?}",
7841 String::from_utf8_lossy(input),
7842 production,
7843 value,
7844 expected
7845 );
7846 }
7847 if tail != expected_tail {
7848 panic!(
7849 "Parsing {:?} as {} left a tail of {:?}, expected {:?}",
7850 String::from_utf8_lossy(input),
7851 production,
7852 tail,
7853 String::from_utf8_lossy(expected_tail)
7854 );
7855 }
7856 if subs[..] != expected_subs[..] {
7857 panic!(
7858 "Parsing {:?} as {} produced a substitutions table of\n\n\
7859 {:#?}\n\n\
7860 but we expected\n\n\
7861 {:#?}",
7862 String::from_utf8_lossy(input),
7863 production,
7864 subs,
7865 expected_subs
7866 );
7867 }
7868 }
7869 }
7870
7871 log!("=== assert_parse_ok PASSED ====================================");
7872 }
7873
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]>,7874 fn simple_assert_parse_ok<P, I1, I2>(
7875 production: &'static str,
7876 input: I1,
7877 expected: P,
7878 expected_tail: I2,
7879 ) where
7880 P: Debug + Parse + PartialEq,
7881 I1: AsRef<[u8]>,
7882 I2: AsRef<[u8]>,
7883 {
7884 assert_parse_ok::<P, _, _, _, _>(production, [], input, expected, expected_tail, []);
7885 }
7886
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]>,7887 fn assert_parse_err<P, S, I>(production: &'static str, subs: S, input: I, expected_error: Error)
7888 where
7889 P: Debug + Parse + PartialEq,
7890 S: AsRef<[Substitutable]>,
7891 I: AsRef<[u8]>,
7892 {
7893 let input = input.as_ref();
7894 let ctx = ParseContext::new(Default::default());
7895 let mut subs = SubstitutionTable::from_iter(subs.as_ref().iter().cloned());
7896
7897 match P::parse(&ctx, &mut subs, IndexStr::from(input)) {
7898 Err(ref error) if *error == expected_error => {}
7899 Err(ref error) => {
7900 panic!(
7901 "Parsing {:?} as {} produced an error of kind {:?}, but we expected kind {:?}",
7902 String::from_utf8_lossy(input),
7903 production,
7904 error,
7905 expected_error
7906 );
7907 }
7908 Ok((value, tail)) => {
7909 panic!(
7910 "Parsing {:?} as {} produced value\
7911 \n\n\
7912 {:#?}\
7913 \n\n\
7914 and tail {:?}, but we expected error kind {:?}",
7915 String::from_utf8_lossy(input),
7916 production,
7917 value,
7918 tail,
7919 expected_error
7920 );
7921 }
7922 }
7923
7924 log!("=== assert_parse_err PASSED ===================================");
7925 }
7926
simple_assert_parse_err<P, I>(production: &'static str, input: I, expected_error: Error) where P: Debug + Parse + PartialEq, I: AsRef<[u8]>,7927 fn simple_assert_parse_err<P, I>(production: &'static str, input: I, expected_error: Error)
7928 where
7929 P: Debug + Parse + PartialEq,
7930 I: AsRef<[u8]>,
7931 {
7932 assert_parse_err::<P, _, _>(production, [], input, expected_error);
7933 }
7934
7935 #[test]
recursion_limit()7936 fn recursion_limit() {
7937 // Build the mangled symbol for the type `*****char` where the "*****"
7938 // is 10,000 pointer indirections. This is a valid type symbol, but
7939 // something that would cause us to blow the stack.
7940 let mut mangled = String::new();
7941 for _ in 0..10_000 {
7942 mangled.push('P');
7943 }
7944 mangled += "c";
7945
7946 simple_assert_parse_err::<TypeHandle, _>("TypeHandle", mangled, Error::TooMuchRecursion);
7947 }
7948
7949 macro_rules! assert_parse {
7950 ( $production:ident {
7951 $( with subs $subs:expr => {
7952 Ok => {
7953 $( $input:expr => {
7954 $expected:expr ,
7955 $expected_tail:expr ,
7956 $expected_new_subs:expr
7957 } )*
7958 }
7959 Err => {
7960 $( $error_input:expr => $error:expr , )*
7961 }
7962 } )*
7963 } ) => {
7964 $( $(
7965 assert_parse_ok::<$production, _, _, _, _>(stringify!($production),
7966 $subs,
7967 $input,
7968 $expected,
7969 $expected_tail,
7970 $expected_new_subs);
7971 )* )*
7972
7973 $( $(
7974 assert_parse_err::<$production, _, _>(stringify!($production),
7975 $subs,
7976 $error_input,
7977 $error);
7978 )* )*
7979 };
7980
7981 ( $production:ident {
7982 Ok => {
7983 $( $input:expr => {
7984 $expected:expr ,
7985 $expected_tail:expr
7986 } )*
7987 }
7988 Err => {
7989 $( $error_input:expr => $error:expr , )*
7990 }
7991 } ) => {
7992 $(
7993 simple_assert_parse_ok::<$production, _, _>(stringify!($production),
7994 $input,
7995 $expected,
7996 $expected_tail);
7997 )*
7998
7999
8000 $(
8001 simple_assert_parse_err::<$production, _>(stringify!($production),
8002 $error_input,
8003 $error);
8004 )*
8005 };
8006 }
8007
8008 #[test]
parse_mangled_name()8009 fn parse_mangled_name() {
8010 assert_parse!(MangledName {
8011 Ok => {
8012 b"_Z3foo..." => {
8013 MangledName::Encoding(
8014 Encoding::Data(
8015 Name::Unscoped(
8016 UnscopedName::Unqualified(
8017 UnqualifiedName::Source(
8018 SourceName(Identifier {
8019 start: 3,
8020 end: 6,
8021 }))))), vec![]),
8022 b"..."
8023 }
8024 b"_GLOBAL__I__Z3foo..." => {
8025 MangledName::GlobalCtorDtor(
8026 GlobalCtorDtor::Ctor(
8027 Box::new(
8028 MangledName::Encoding(
8029 Encoding::Data(
8030 Name::Unscoped(
8031 UnscopedName::Unqualified(
8032 UnqualifiedName::Source(
8033 SourceName(
8034 Identifier {
8035 start: 14,
8036 end: 17,
8037 }))))), vec![])))),
8038 b"..."
8039 }
8040 }
8041 Err => {
8042 b"_Y" => Error::UnexpectedText,
8043 b"_Z" => Error::UnexpectedEnd,
8044 b"_" => Error::UnexpectedEnd,
8045 b"" => Error::UnexpectedEnd,
8046 b"_GLOBAL_" => Error::UnexpectedEnd,
8047 }
8048 });
8049 }
8050
8051 #[test]
parse_encoding()8052 fn parse_encoding() {
8053 assert_parse!(Encoding {
8054 with subs [] => {
8055 Ok => {
8056 b"3fooi..." => {
8057 Encoding::Function(
8058 Name::Unscoped(
8059 UnscopedName::Unqualified(
8060 UnqualifiedName::Source(
8061 SourceName(Identifier {
8062 start: 1,
8063 end: 4,
8064 })))),
8065 BareFunctionType(vec![
8066 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))
8067 ])),
8068 b"...",
8069 []
8070 }
8071 b"3foo..." => {
8072 Encoding::Data(
8073 Name::Unscoped(
8074 UnscopedName::Unqualified(
8075 UnqualifiedName::Source(
8076 SourceName(Identifier {
8077 start: 1,
8078 end: 4,
8079 }))))),
8080 b"...",
8081 []
8082 }
8083 b"GV3abc..." => {
8084 Encoding::Special(
8085 SpecialName::Guard(
8086 Name::Unscoped(
8087 UnscopedName::Unqualified(
8088 UnqualifiedName::Source(
8089 SourceName(Identifier {
8090 start: 3,
8091 end: 6,
8092 })))))),
8093 b"...",
8094 []
8095 }
8096 }
8097 Err => {
8098 b"zzz" => Error::UnexpectedText,
8099 b"" => Error::UnexpectedEnd,
8100 }
8101 }
8102 });
8103 }
8104
8105 #[test]
parse_global_ctor_dtor()8106 fn parse_global_ctor_dtor() {
8107 assert_parse!(GlobalCtorDtor {
8108 Ok => {
8109 b"_I__Z3foo..." => {
8110 GlobalCtorDtor::Ctor(
8111 Box::new(
8112 MangledName::Encoding(
8113 Encoding::Data(
8114 Name::Unscoped(
8115 UnscopedName::Unqualified(
8116 UnqualifiedName::Source(
8117 SourceName(
8118 Identifier {
8119 start: 6,
8120 end: 9,
8121 }))))), vec![]))),
8122 b"..."
8123 }
8124 b".I__Z3foo..." => {
8125 GlobalCtorDtor::Ctor(
8126 Box::new(
8127 MangledName::Encoding(
8128 Encoding::Data(
8129 Name::Unscoped(
8130 UnscopedName::Unqualified(
8131 UnqualifiedName::Source(
8132 SourceName(
8133 Identifier {
8134 start: 6,
8135 end: 9,
8136 }))))), vec![]))),
8137 b"..."
8138 }
8139 b"$I__Z3foo..." => {
8140 GlobalCtorDtor::Ctor(
8141 Box::new(
8142 MangledName::Encoding(
8143 Encoding::Data(
8144 Name::Unscoped(
8145 UnscopedName::Unqualified(
8146 UnqualifiedName::Source(
8147 SourceName(
8148 Identifier {
8149 start: 6,
8150 end: 9,
8151 }))))), vec![]))),
8152 b"..."
8153 }
8154 b"_D__Z3foo..." => {
8155 GlobalCtorDtor::Dtor(
8156 Box::new(
8157 MangledName::Encoding(
8158 Encoding::Data(
8159 Name::Unscoped(
8160 UnscopedName::Unqualified(
8161 UnqualifiedName::Source(
8162 SourceName(
8163 Identifier {
8164 start: 6,
8165 end: 9,
8166 }))))), vec![]))),
8167 b"..."
8168 }
8169 b".D__Z3foo..." => {
8170 GlobalCtorDtor::Dtor(
8171 Box::new(
8172 MangledName::Encoding(
8173 Encoding::Data(
8174 Name::Unscoped(
8175 UnscopedName::Unqualified(
8176 UnqualifiedName::Source(
8177 SourceName(
8178 Identifier {
8179 start: 6,
8180 end: 9,
8181 }))))), vec![]))),
8182 b"..."
8183 }
8184 b"$D__Z3foo..." => {
8185 GlobalCtorDtor::Dtor(
8186 Box::new(
8187 MangledName::Encoding(
8188 Encoding::Data(
8189 Name::Unscoped(
8190 UnscopedName::Unqualified(
8191 UnqualifiedName::Source(
8192 SourceName(
8193 Identifier {
8194 start: 6,
8195 end: 9,
8196 }))))), vec![]))),
8197 b"..."
8198 }
8199 }
8200 Err => {
8201 b"_I" => Error::UnexpectedEnd,
8202 b"_" => Error::UnexpectedEnd,
8203 b"" => Error::UnexpectedEnd,
8204 b"blag" => Error::UnexpectedText,
8205 b"_J" => Error::UnexpectedText,
8206 b"_IJ" => Error::UnexpectedText,
8207 }
8208 });
8209 }
8210
8211 #[test]
parse_name()8212 fn parse_name() {
8213 assert_parse!(Name {
8214 with subs [
8215 Substitutable::Prefix(
8216 Prefix::Unqualified(
8217 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::New)))),
8218 Substitutable::Prefix(
8219 Prefix::Nested(PrefixHandle::BackReference(0),
8220 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::New)))),
8221 ] => {
8222 Ok => {
8223 b"NS0_3abcE..." => {
8224 Name::Nested(NestedName::Unqualified(CvQualifiers::default(),
8225 None,
8226 PrefixHandle::BackReference(1),
8227 UnqualifiedName::Source(SourceName(Identifier {
8228 start: 5,
8229 end: 8,
8230 })))),
8231 b"...",
8232 []
8233 }
8234 b"3abc..." => {
8235 Name::Unscoped(
8236 UnscopedName::Unqualified(
8237 UnqualifiedName::Source(
8238 SourceName(Identifier {
8239 start: 1,
8240 end: 4,
8241 })))),
8242 b"...",
8243 []
8244 }
8245 b"dlIcE..." => {
8246 Name::UnscopedTemplate(
8247 UnscopedTemplateNameHandle::BackReference(2),
8248 TemplateArgs(vec![
8249 TemplateArg::Type(
8250 TypeHandle::Builtin(
8251 BuiltinType::Standard(StandardBuiltinType::Char)))
8252 ])),
8253 b"...",
8254 [
8255 Substitutable::UnscopedTemplateName(
8256 UnscopedTemplateName(
8257 UnscopedName::Unqualified(
8258 UnqualifiedName::Operator(
8259 OperatorName::Simple(
8260 SimpleOperatorName::Delete))))),
8261 ]
8262 }
8263 b"Z3abcEs..." => {
8264 Name::Local(
8265 LocalName::Relative(
8266 Box::new(Encoding::Data(
8267 Name::Unscoped(
8268 UnscopedName::Unqualified(
8269 UnqualifiedName::Source(
8270 SourceName(Identifier {
8271 start: 2,
8272 end: 5,
8273 })))))),
8274 None,
8275 None)),
8276 b"...",
8277 []
8278 }
8279 }
8280 Err => {
8281 b"zzz" => Error::UnexpectedText,
8282 b"" => Error::UnexpectedEnd,
8283 }
8284 }
8285 });
8286 }
8287
8288 #[test]
parse_unscoped_template_name_handle()8289 fn parse_unscoped_template_name_handle() {
8290 assert_parse!(UnscopedTemplateNameHandle {
8291 with subs [
8292 Substitutable::UnscopedTemplateName(
8293 UnscopedTemplateName(
8294 UnscopedName::Unqualified(
8295 UnqualifiedName::Operator(
8296 OperatorName::Simple(
8297 SimpleOperatorName::New))))),
8298 ] => {
8299 Ok => {
8300 b"S_..." => {
8301 UnscopedTemplateNameHandle::BackReference(0),
8302 b"...",
8303 []
8304 }
8305 b"dl..." => {
8306 UnscopedTemplateNameHandle::BackReference(1),
8307 b"...",
8308 [
8309 Substitutable::UnscopedTemplateName(
8310 UnscopedTemplateName(
8311 UnscopedName::Unqualified(
8312 UnqualifiedName::Operator(
8313 OperatorName::Simple(
8314 SimpleOperatorName::Delete)))))
8315 ]
8316 }
8317 }
8318 Err => {
8319 b"zzzz" => Error::UnexpectedText,
8320 b"" => Error::UnexpectedEnd,
8321 }
8322 }
8323 });
8324 }
8325
8326 #[test]
parse_nested_name()8327 fn parse_nested_name() {
8328 // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
8329 // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
8330 assert_parse!(NestedName {
8331 with subs [
8332 Substitutable::Prefix(
8333 Prefix::Unqualified(
8334 UnqualifiedName::Operator(
8335 OperatorName::Simple(
8336 SimpleOperatorName::New)))),
8337 ] => {
8338 Ok => {
8339 b"NKOS_3abcE..." => {
8340 NestedName::Unqualified(
8341 CvQualifiers {
8342 restrict: false,
8343 volatile: false,
8344 const_: true,
8345 },
8346 Some(RefQualifier::RValueRef),
8347 PrefixHandle::BackReference(0),
8348 UnqualifiedName::Source(
8349 SourceName(Identifier {
8350 start: 6,
8351 end: 9,
8352 }))),
8353 b"...",
8354 []
8355 }
8356 b"NOS_3abcE..." => {
8357 NestedName::Unqualified(
8358 CvQualifiers {
8359 restrict: false,
8360 volatile: false,
8361 const_: false,
8362 },
8363 Some(RefQualifier::RValueRef),
8364 PrefixHandle::BackReference(0),
8365 UnqualifiedName::Source(
8366 SourceName(Identifier {
8367 start: 5,
8368 end: 8,
8369 }))),
8370 b"...",
8371 []
8372 }
8373 b"NS_3abcE..." => {
8374 NestedName::Unqualified(
8375 CvQualifiers {
8376 restrict: false,
8377 volatile: false,
8378 const_: false,
8379 },
8380 None,
8381 PrefixHandle::BackReference(0),
8382 UnqualifiedName::Source(
8383 SourceName(Identifier {
8384 start: 4,
8385 end: 7,
8386 }))),
8387 b"...",
8388 []
8389 }
8390 b"NKOS_3abcIJEEE..." => {
8391 NestedName::Template(
8392 CvQualifiers {
8393 restrict: false,
8394 volatile: false,
8395 const_: true,
8396 },
8397 Some(RefQualifier::RValueRef),
8398 PrefixHandle::NonSubstitution(NonSubstitution(0))),
8399 b"...",
8400 [
8401 Substitutable::Prefix(
8402 Prefix::Nested(
8403 PrefixHandle::BackReference(0),
8404 UnqualifiedName::Source(
8405 SourceName(Identifier {
8406 start: 6,
8407 end: 9,
8408 })))),
8409 ]
8410 }
8411 b"NOS_3abcIJEEE..." => {
8412 NestedName::Template(
8413 CvQualifiers {
8414 restrict: false,
8415 volatile: false,
8416 const_: false,
8417 },
8418 Some(RefQualifier::RValueRef),
8419 PrefixHandle::NonSubstitution(NonSubstitution(0))),
8420 b"...",
8421 [
8422 Substitutable::Prefix(
8423 Prefix::Nested(
8424 PrefixHandle::BackReference(0),
8425 UnqualifiedName::Source(
8426 SourceName(Identifier {
8427 start: 5,
8428 end: 8,
8429 })))),
8430 ]
8431 }
8432 b"NS_3abcIJEEE..." => {
8433 NestedName::Template(
8434 CvQualifiers {
8435 restrict: false,
8436 volatile: false,
8437 const_: false,
8438 },
8439 None,
8440 PrefixHandle::NonSubstitution(NonSubstitution(0))),
8441 b"...",
8442 [
8443 Substitutable::Prefix(
8444 Prefix::Nested(
8445 PrefixHandle::BackReference(0),
8446 UnqualifiedName::Source(
8447 SourceName(Identifier {
8448 start: 4,
8449 end: 7,
8450 })))),
8451 ]
8452 }
8453 }
8454 Err => {
8455 // Ends with a prefix that is not a name or template.
8456 b"NS_E..." => Error::UnexpectedText,
8457 b"NS_DttrEE..." => Error::UnexpectedText,
8458
8459 b"zzz" => Error::UnexpectedText,
8460 b"Nzzz" => Error::UnexpectedText,
8461 b"NKzzz" => Error::UnexpectedText,
8462 b"NKOzzz" => Error::UnexpectedText,
8463 b"NKO3abczzz" => Error::UnexpectedText,
8464 b"NKO3abc3abczzz" => Error::UnexpectedText,
8465 b"" => Error::UnexpectedEnd,
8466 b"N" => Error::UnexpectedEnd,
8467 b"NK" => Error::UnexpectedEnd,
8468 b"NKO" => Error::UnexpectedEnd,
8469 b"NKO3abc" => Error::UnexpectedEnd,
8470 b"NKO3abc3abc" => Error::UnexpectedEnd,
8471 }
8472 }
8473 });
8474 }
8475
8476 #[test]
parse_prefix_handle()8477 fn parse_prefix_handle() {
8478 // <prefix> ::= <unqualified-name>
8479 // ::= <prefix> <unqualified-name>
8480 // ::= <template-prefix> <template-args>
8481 // ::= <template-param>
8482 // ::= <decltype>
8483 // ::= <prefix> <data-member-prefix>
8484 // ::= <substitution>
8485 assert_parse!(PrefixHandle {
8486 with subs [
8487 Substitutable::Prefix(
8488 Prefix::Unqualified(
8489 UnqualifiedName::Operator(
8490 OperatorName::Simple(
8491 SimpleOperatorName::New)))),
8492 ] => {
8493 Ok => {
8494 b"3foo..." => {
8495 PrefixHandle::BackReference(1),
8496 b"...",
8497 [
8498 Substitutable::Prefix(
8499 Prefix::Unqualified(
8500 UnqualifiedName::Source(
8501 SourceName(Identifier {
8502 start: 1,
8503 end: 4,
8504 }))))
8505 ]
8506 }
8507 b"3abc3def..." => {
8508 PrefixHandle::BackReference(2),
8509 b"...",
8510 [
8511 Substitutable::Prefix(
8512 Prefix::Unqualified(
8513 UnqualifiedName::Source(
8514 SourceName(Identifier {
8515 start: 1,
8516 end: 4,
8517 })))),
8518 Substitutable::Prefix(
8519 Prefix::Nested(
8520 PrefixHandle::BackReference(1),
8521 UnqualifiedName::Source(
8522 SourceName(Identifier {
8523 start: 5,
8524 end: 8,
8525 })))),
8526 ]
8527 }
8528 b"3fooIJEE..." => {
8529 PrefixHandle::BackReference(2),
8530 b"...",
8531 [
8532 Substitutable::Prefix(
8533 Prefix::Unqualified(
8534 UnqualifiedName::Source(
8535 SourceName(Identifier {
8536 start: 1,
8537 end: 4,
8538 })))),
8539 Substitutable::Prefix(
8540 Prefix::Template(PrefixHandle::BackReference(1),
8541 TemplateArgs(vec![
8542 TemplateArg::ArgPack(vec![]),
8543 ])))
8544 ]
8545 }
8546 b"T_..." => {
8547 PrefixHandle::BackReference(1),
8548 b"...",
8549 [
8550 Substitutable::Prefix(Prefix::TemplateParam(TemplateParam(0))),
8551 ]
8552 }
8553 b"DTtrE..." => {
8554 PrefixHandle::BackReference(1),
8555 b"...",
8556 [
8557 Substitutable::Prefix(
8558 Prefix::Decltype(
8559 Decltype::Expression(Expression::Rethrow))),
8560 ]
8561 }
8562 b"3abc3defM..." => {
8563 PrefixHandle::BackReference(2),
8564 b"...",
8565 [
8566 Substitutable::Prefix(
8567 Prefix::Unqualified(
8568 UnqualifiedName::Source(
8569 SourceName(Identifier {
8570 start: 1,
8571 end: 4,
8572 })))),
8573 Substitutable::Prefix(
8574 Prefix::DataMember(
8575 PrefixHandle::BackReference(1),
8576 DataMemberPrefix(
8577 SourceName(Identifier {
8578 start: 5,
8579 end: 8,
8580 })))),
8581 ]
8582 }
8583 b"S_..." => {
8584 PrefixHandle::BackReference(0),
8585 b"...",
8586 []
8587 }
8588 // The trailing E and <nested-name> case...
8589 b"3abc3defE..." => {
8590 PrefixHandle::NonSubstitution(NonSubstitution(0)),
8591 b"E...",
8592 [
8593 Substitutable::Prefix(
8594 Prefix::Unqualified(
8595 UnqualifiedName::Source(
8596 SourceName(Identifier {
8597 start: 1,
8598 end: 4,
8599 })))),
8600 ]
8601 }
8602 }
8603 Err => {
8604 b"zzz" => Error::UnexpectedText,
8605 b"" => Error::UnexpectedEnd,
8606 }
8607 }
8608 });
8609 }
8610
8611 #[test]
parse_type_handle()8612 fn parse_type_handle() {
8613 assert_parse!(TypeHandle {
8614 with subs [
8615 Substitutable::Type(
8616 Type::PointerTo(
8617 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
8618 ] => {
8619 Ok => {
8620 b"S_..." => {
8621 TypeHandle::BackReference(0),
8622 b"...",
8623 []
8624 }
8625 b"c..." => {
8626 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)),
8627 b"...",
8628 []
8629 }
8630 b"FS_E..." => {
8631 TypeHandle::BackReference(1),
8632 b"...",
8633 [
8634 Substitutable::Type(
8635 Type::Function(FunctionType {
8636 cv_qualifiers: CvQualifiers {
8637 restrict: false,
8638 volatile: false,
8639 const_: false,
8640 },
8641 transaction_safe: false,
8642 extern_c: false,
8643 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
8644 ref_qualifier: None,
8645 })),
8646 ]
8647 }
8648 b"A_S_..." => {
8649 TypeHandle::BackReference(1),
8650 b"...",
8651 [
8652 Substitutable::Type(
8653 Type::Array(ArrayType::NoDimension(TypeHandle::BackReference(0)))),
8654 ]
8655 }
8656 b"MS_S_..." => {
8657 TypeHandle::BackReference(1),
8658 b"...",
8659 [
8660 Substitutable::Type(
8661 Type::PointerToMember(
8662 PointerToMemberType(TypeHandle::BackReference(0),
8663 TypeHandle::BackReference(0)))),
8664 ]
8665 }
8666 b"T_..." => {
8667 TypeHandle::BackReference(1),
8668 b"...",
8669 [
8670 Substitutable::Type(Type::TemplateParam(TemplateParam(0))),
8671 ]
8672 }
8673 b"T_IS_E..." => {
8674 TypeHandle::BackReference(2),
8675 b"...",
8676 [
8677 Substitutable::TemplateTemplateParam(
8678 TemplateTemplateParam(TemplateParam(0))),
8679 Substitutable::Type(
8680 Type::TemplateTemplate(
8681 TemplateTemplateParamHandle::BackReference(1),
8682 TemplateArgs(vec![
8683 TemplateArg::Type(TypeHandle::BackReference(0))
8684 ]))),
8685 ]
8686 }
8687 b"DTtrE..." => {
8688 TypeHandle::BackReference(1),
8689 b"...",
8690 [
8691 Substitutable::Type(
8692 Type::Decltype(Decltype::Expression(Expression::Rethrow))),
8693 ]
8694 }
8695 b"KS_..." => {
8696 TypeHandle::BackReference(1),
8697 b"...",
8698 [
8699 Substitutable::Type(Type::Qualified(CvQualifiers {
8700 restrict: false,
8701 volatile: false,
8702 const_: true,
8703 }, TypeHandle::BackReference(0)))
8704 ]
8705 }
8706 b"PS_..." => {
8707 TypeHandle::BackReference(1),
8708 b"...",
8709 [
8710 Substitutable::Type(Type::PointerTo(TypeHandle::BackReference(0)))
8711 ]
8712 }
8713 b"RS_..." => {
8714 TypeHandle::BackReference(1),
8715 b"...",
8716 [
8717 Substitutable::Type(Type::LvalueRef(TypeHandle::BackReference(0)))
8718 ]
8719 }
8720 b"OS_..." => {
8721 TypeHandle::BackReference(1),
8722 b"...",
8723 [
8724 Substitutable::Type(Type::RvalueRef(TypeHandle::BackReference(0)))
8725 ]
8726 }
8727 b"CS_..." => {
8728 TypeHandle::BackReference(1),
8729 b"...",
8730 [
8731 Substitutable::Type(Type::Complex(TypeHandle::BackReference(0)))
8732 ]
8733 }
8734 b"GS_..." => {
8735 TypeHandle::BackReference(1),
8736 b"...",
8737 [
8738 Substitutable::Type(Type::Imaginary(TypeHandle::BackReference(0)))
8739 ]
8740 }
8741 b"U3abcS_..." => {
8742 TypeHandle::BackReference(1),
8743 b"...",
8744 [
8745 Substitutable::Type(
8746 Type::VendorExtension(
8747 SourceName(Identifier {
8748 start: 2,
8749 end: 5,
8750 }),
8751 None,
8752 TypeHandle::BackReference(0)))
8753 ]
8754 }
8755 b"U3abcIS_ES_..." => {
8756 TypeHandle::BackReference(1),
8757 b"...",
8758 [
8759 Substitutable::Type(
8760 Type::VendorExtension(
8761 SourceName(Identifier {
8762 start: 2,
8763 end: 5,
8764 }),
8765 Some(TemplateArgs(vec![
8766 TemplateArg::Type(TypeHandle::BackReference(0))
8767 ])),
8768 TypeHandle::BackReference(0)))
8769 ]
8770 }
8771 b"DpS_..." => {
8772 TypeHandle::BackReference(1),
8773 b"...",
8774 [
8775 Substitutable::Type(
8776 Type::PackExpansion(TypeHandle::BackReference(0))),
8777 ]
8778 }
8779 b"3abc..." => {
8780 TypeHandle::BackReference(1),
8781 b"...",
8782 [
8783 Substitutable::Type(
8784 Type::ClassEnum(
8785 ClassEnumType::Named(
8786 Name::Unscoped(
8787 UnscopedName::Unqualified(
8788 UnqualifiedName::Source(
8789 SourceName(Identifier {
8790 start: 1,
8791 end: 4,
8792 })))))))
8793 ]
8794 }
8795 }
8796 Err => {
8797 b"P" => Error::UnexpectedEnd,
8798 b"R" => Error::UnexpectedEnd,
8799 b"O" => Error::UnexpectedEnd,
8800 b"C" => Error::UnexpectedEnd,
8801 b"G" => Error::UnexpectedEnd,
8802 b"Dp" => Error::UnexpectedEnd,
8803 b"D" => Error::UnexpectedEnd,
8804 b"P" => Error::UnexpectedEnd,
8805 b"" => Error::UnexpectedEnd,
8806 }
8807 }
8808 });
8809 }
8810
8811 #[test]
parse_function_type()8812 fn parse_function_type() {
8813 assert_parse!(FunctionType {
8814 with subs [
8815 Substitutable::Type(
8816 Type::PointerTo(
8817 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
8818 ] => {
8819 Ok => {
8820 b"KDxFYS_RE..." => {
8821 FunctionType {
8822 cv_qualifiers: CvQualifiers {
8823 restrict: false,
8824 volatile: false,
8825 const_: true,
8826 },
8827 transaction_safe: true,
8828 extern_c: true,
8829 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
8830 ref_qualifier: Some(RefQualifier::LValueRef),
8831 },
8832 b"...",
8833 []
8834 }
8835 b"DxFYS_RE..." => {
8836 FunctionType {
8837 cv_qualifiers: CvQualifiers {
8838 restrict: false,
8839 volatile: false,
8840 const_: false,
8841 },
8842 transaction_safe: true,
8843 extern_c: true,
8844 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
8845 ref_qualifier: Some(RefQualifier::LValueRef),
8846 },
8847 b"...",
8848 []
8849 }
8850 b"FYS_RE..." => {
8851 FunctionType {
8852 cv_qualifiers: CvQualifiers {
8853 restrict: false,
8854 volatile: false,
8855 const_: false,
8856 },
8857 transaction_safe: false,
8858 extern_c: true,
8859 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
8860 ref_qualifier: Some(RefQualifier::LValueRef),
8861 },
8862 b"...",
8863 []
8864 }
8865 b"FS_RE..." => {
8866 FunctionType {
8867 cv_qualifiers: CvQualifiers {
8868 restrict: false,
8869 volatile: false,
8870 const_: false,
8871 },
8872 transaction_safe: false,
8873 extern_c: false,
8874 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
8875 ref_qualifier: Some(RefQualifier::LValueRef),
8876 },
8877 b"...",
8878 []
8879 }
8880 b"FS_E..." => {
8881 FunctionType {
8882 cv_qualifiers: CvQualifiers {
8883 restrict: false,
8884 volatile: false,
8885 const_: false,
8886 },
8887 transaction_safe: false,
8888 extern_c: false,
8889 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
8890 ref_qualifier: None,
8891 },
8892 b"...",
8893 []
8894 }
8895 }
8896 Err => {
8897 b"DFYS_E" => Error::UnexpectedText,
8898 b"KKFS_E" => Error::UnexpectedText,
8899 b"FYS_..." => Error::UnexpectedText,
8900 b"FYS_" => Error::UnexpectedEnd,
8901 b"F" => Error::UnexpectedEnd,
8902 b"" => Error::UnexpectedEnd,
8903 }
8904 }
8905 });
8906 }
8907
8908 #[test]
parse_bare_function_type()8909 fn parse_bare_function_type() {
8910 assert_parse!(BareFunctionType {
8911 with subs [
8912 Substitutable::Type(
8913 Type::PointerTo(
8914 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
8915 ] => {
8916 Ok => {
8917 b"S_S_..." => {
8918 BareFunctionType(vec![
8919 TypeHandle::BackReference(0),
8920 TypeHandle::BackReference(0),
8921 ]),
8922 b"...",
8923 []
8924 }
8925 }
8926 Err => {
8927 b"" => Error::UnexpectedEnd,
8928 }
8929 }
8930 });
8931 }
8932
8933 #[test]
parse_decltype()8934 fn parse_decltype() {
8935 assert_parse!(Decltype {
8936 Ok => {
8937 b"DTtrE..." => {
8938 Decltype::Expression(Expression::Rethrow),
8939 b"..."
8940 }
8941 b"DttrE..." => {
8942 Decltype::IdExpression(Expression::Rethrow),
8943 b"..."
8944 }
8945 }
8946 Err => {
8947 b"Dtrtz" => Error::UnexpectedText,
8948 b"DTrtz" => Error::UnexpectedText,
8949 b"Dz" => Error::UnexpectedText,
8950 b"Dtrt" => Error::UnexpectedText,
8951 b"DTrt" => Error::UnexpectedText,
8952 b"Dt" => Error::UnexpectedEnd,
8953 b"DT" => Error::UnexpectedEnd,
8954 b"D" => Error::UnexpectedEnd,
8955 b"" => Error::UnexpectedEnd,
8956 }
8957 });
8958 }
8959
8960 #[test]
parse_class_enum_type()8961 fn parse_class_enum_type() {
8962 assert_parse!(ClassEnumType {
8963 Ok => {
8964 b"3abc..." => {
8965 ClassEnumType::Named(
8966 Name::Unscoped(
8967 UnscopedName::Unqualified(
8968 UnqualifiedName::Source(
8969 SourceName(Identifier {
8970 start: 1,
8971 end: 4,
8972 }))))),
8973 b"..."
8974 }
8975 b"Ts3abc..." => {
8976 ClassEnumType::ElaboratedStruct(
8977 Name::Unscoped(
8978 UnscopedName::Unqualified(
8979 UnqualifiedName::Source(
8980 SourceName(Identifier {
8981 start: 3,
8982 end: 6,
8983 }))))),
8984 b"..."
8985 }
8986 b"Tu3abc..." => {
8987 ClassEnumType::ElaboratedUnion(
8988 Name::Unscoped(
8989 UnscopedName::Unqualified(
8990 UnqualifiedName::Source(
8991 SourceName(Identifier {
8992 start: 3,
8993 end: 6,
8994 }))))),
8995 b"..."
8996 }
8997 b"Te3abc..." => {
8998 ClassEnumType::ElaboratedEnum(
8999 Name::Unscoped(
9000 UnscopedName::Unqualified(
9001 UnqualifiedName::Source(
9002 SourceName(Identifier {
9003 start: 3,
9004 end: 6,
9005 }))))),
9006 b"..."
9007 }
9008 }
9009 Err => {
9010 b"zzz" => Error::UnexpectedText,
9011 b"Tzzz" => Error::UnexpectedText,
9012 b"T" => Error::UnexpectedEnd,
9013 b"" => Error::UnexpectedEnd,
9014 }
9015 });
9016 }
9017
9018 #[test]
parse_array_type()9019 fn parse_array_type() {
9020 assert_parse!(ArrayType {
9021 with subs [
9022 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9023 ] => {
9024 Ok => {
9025 b"A10_S_..." => {
9026 ArrayType::DimensionNumber(10, TypeHandle::BackReference(0)),
9027 b"...",
9028 []
9029 }
9030 b"A10_Sb..." => {
9031 ArrayType::DimensionNumber(10,
9032 TypeHandle::WellKnown(
9033 WellKnownComponent::StdString1)),
9034 b"...",
9035 []
9036 }
9037 b"Atr_S_..." => {
9038 ArrayType::DimensionExpression(Expression::Rethrow,
9039 TypeHandle::BackReference(0)),
9040 b"...",
9041 []
9042 }
9043 b"A_S_..." => {
9044 ArrayType::NoDimension(TypeHandle::BackReference(0)),
9045 b"...",
9046 []
9047 }
9048 }
9049 Err => {
9050 b"A10_" => Error::UnexpectedEnd,
9051 b"A10" => Error::UnexpectedEnd,
9052 b"A" => Error::UnexpectedEnd,
9053 b"" => Error::UnexpectedEnd,
9054 b"A10_..." => Error::UnexpectedText,
9055 b"A10..." => Error::UnexpectedText,
9056 b"A..." => Error::UnexpectedText,
9057 b"..." => Error::UnexpectedText,
9058 }
9059 }
9060 });
9061 }
9062
9063 #[test]
parse_vector_type()9064 fn parse_vector_type() {
9065 assert_parse!(VectorType {
9066 with subs [
9067 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9068 ] => {
9069 Ok => {
9070 b"Dv10_S_..." => {
9071 VectorType::DimensionNumber(10, TypeHandle::BackReference(0)),
9072 b"...",
9073 []
9074 }
9075 b"Dv10_Sb..." => {
9076 VectorType::DimensionNumber(10,
9077 TypeHandle::WellKnown(
9078 WellKnownComponent::StdString1)),
9079 b"...",
9080 []
9081 }
9082 b"Dv_tr_S_..." => {
9083 VectorType::DimensionExpression(Expression::Rethrow,
9084 TypeHandle::BackReference(0)),
9085 b"...",
9086 []
9087 }
9088 }
9089 Err => {
9090 b"Dq" => Error::UnexpectedText,
9091 b"Dv" => Error::UnexpectedEnd,
9092 b"Dv42_" => Error::UnexpectedEnd,
9093 b"Dv42_..." => Error::UnexpectedText,
9094 b"Dvtr_" => Error::UnexpectedText,
9095 b"" => Error::UnexpectedEnd,
9096 b"..." => Error::UnexpectedText,
9097 }
9098 }
9099 });
9100 }
9101
9102 #[test]
parse_pointer_to_member_type()9103 fn parse_pointer_to_member_type() {
9104 assert_parse!(PointerToMemberType {
9105 with subs [
9106 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9107 ] => {
9108 Ok => {
9109 b"MS_S_..." => {
9110 PointerToMemberType(TypeHandle::BackReference(0),
9111 TypeHandle::BackReference(0)),
9112 b"...",
9113 []
9114 }
9115 }
9116 Err => {
9117 b"MS_S" => Error::UnexpectedEnd,
9118 b"MS_" => Error::UnexpectedEnd,
9119 b"MS" => Error::UnexpectedEnd,
9120 b"M" => Error::UnexpectedEnd,
9121 b"" => Error::UnexpectedEnd,
9122 b"MS_..." => Error::UnexpectedText,
9123 b"M..." => Error::UnexpectedText,
9124 b"..." => Error::UnexpectedText,
9125 }
9126 }
9127 });
9128 }
9129
9130 #[test]
parse_template_template_param_handle()9131 fn parse_template_template_param_handle() {
9132 assert_parse!(TemplateTemplateParamHandle {
9133 with subs [
9134 Substitutable::TemplateTemplateParam(TemplateTemplateParam(TemplateParam(0)))
9135 ] => {
9136 Ok => {
9137 b"S_..." => {
9138 TemplateTemplateParamHandle::BackReference(0),
9139 b"...",
9140 []
9141 }
9142 b"T1_..." => {
9143 TemplateTemplateParamHandle::BackReference(1),
9144 b"...",
9145 [
9146 Substitutable::TemplateTemplateParam(TemplateTemplateParam(TemplateParam(2)))
9147 ]
9148 }
9149 }
9150 Err => {
9151 b"S" => Error::UnexpectedText,
9152 b"T" => Error::UnexpectedEnd,
9153 b"" => Error::UnexpectedEnd,
9154 b"S..." => Error::UnexpectedText,
9155 b"T..." => Error::UnexpectedText,
9156 b"..." => Error::UnexpectedText,
9157 }
9158 }
9159 });
9160 }
9161
9162 #[test]
parse_template_args()9163 fn parse_template_args() {
9164 assert_parse!(TemplateArgs {
9165 with subs [
9166 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9167 ] => {
9168 Ok => {
9169 b"IS_E..." => {
9170 TemplateArgs(vec![TemplateArg::Type(TypeHandle::BackReference(0))]),
9171 b"...",
9172 []
9173 }
9174 b"IS_S_S_S_E..." => {
9175 TemplateArgs(vec![
9176 TemplateArg::Type(TypeHandle::BackReference(0)),
9177 TemplateArg::Type(TypeHandle::BackReference(0)),
9178 TemplateArg::Type(TypeHandle::BackReference(0)),
9179 TemplateArg::Type(TypeHandle::BackReference(0)),
9180 ]),
9181 b"...",
9182 []
9183 }
9184 }
9185 Err => {
9186 b"zzz" => Error::UnexpectedText,
9187 b"IE" => Error::UnexpectedText,
9188 b"IS_" => Error::UnexpectedEnd,
9189 b"I" => Error::UnexpectedEnd,
9190 b"" => Error::UnexpectedEnd,
9191 }
9192 }
9193 });
9194 }
9195
9196 #[test]
parse_template_arg()9197 fn parse_template_arg() {
9198 assert_parse!(TemplateArg {
9199 with subs [
9200 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9201 ] => {
9202 Ok => {
9203 b"S_..." => {
9204 TemplateArg::Type(TypeHandle::BackReference(0)),
9205 b"...",
9206 []
9207 }
9208 b"XtrE..." => {
9209 TemplateArg::Expression(Expression::Rethrow),
9210 b"...",
9211 []
9212 }
9213 b"XsrS_1QE..." => {
9214 TemplateArg::Expression(
9215 Expression::UnresolvedName(
9216 UnresolvedName::Nested1(
9217 UnresolvedTypeHandle::BackReference(0),
9218 vec![],
9219 BaseUnresolvedName::Name(
9220 SimpleId(
9221 SourceName(Identifier {
9222 start: 6,
9223 end: 7
9224 }),
9225 None
9226 )
9227 )
9228 )
9229 )
9230 ),
9231 b"...",
9232 []
9233 }
9234 b"XsrS_1QIlEE..." => {
9235 TemplateArg::Expression(
9236 Expression::UnresolvedName(
9237 UnresolvedName::Nested1(
9238 UnresolvedTypeHandle::BackReference(0),
9239 vec![],
9240 BaseUnresolvedName::Name(
9241 SimpleId(
9242 SourceName(Identifier {
9243 start: 6,
9244 end: 7
9245 }),
9246 Some(
9247 TemplateArgs(
9248 vec![
9249 TemplateArg::Type(
9250 TypeHandle::Builtin(
9251 BuiltinType::Standard(
9252 StandardBuiltinType::Long
9253 )
9254 )
9255 )
9256 ]
9257 )
9258 )
9259 )
9260 )
9261 )
9262 )
9263 ),
9264 b"...",
9265 []
9266 }
9267 b"LS_E..." => {
9268 TemplateArg::SimpleExpression(
9269 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 3)),
9270 b"...",
9271 []
9272 }
9273 b"JE..." => {
9274 TemplateArg::ArgPack(vec![]),
9275 b"...",
9276 []
9277 }
9278 b"JS_XtrELS_EJEE..." => {
9279 TemplateArg::ArgPack(vec![
9280 TemplateArg::Type(TypeHandle::BackReference(0)),
9281 TemplateArg::Expression(Expression::Rethrow),
9282 TemplateArg::SimpleExpression(
9283 ExprPrimary::Literal(TypeHandle::BackReference(0), 10, 10)),
9284 TemplateArg::ArgPack(vec![]),
9285 ]),
9286 b"...",
9287 []
9288 }
9289 }
9290 Err => {
9291 b"..." => Error::UnexpectedText,
9292 b"X..." => Error::UnexpectedText,
9293 b"J..." => Error::UnexpectedText,
9294 b"JS_..." => Error::UnexpectedText,
9295 b"JS_" => Error::UnexpectedEnd,
9296 b"X" => Error::UnexpectedEnd,
9297 b"J" => Error::UnexpectedEnd,
9298 b"" => Error::UnexpectedEnd,
9299 }
9300 }
9301 });
9302 }
9303
9304 #[test]
parse_expression()9305 fn parse_expression() {
9306 assert_parse!(Expression {
9307 with subs [
9308 Substitutable::Type(
9309 Type::PointerTo(TypeHandle::Builtin(
9310 BuiltinType::Standard(StandardBuiltinType::Int)))),
9311 ] => {
9312 Ok => {
9313 b"psLS_1E..." => {
9314 Expression::Unary(OperatorName::Simple(SimpleOperatorName::UnaryPlus),
9315 Box::new(Expression::Primary(
9316 ExprPrimary::Literal(
9317 TypeHandle::BackReference(0),
9318 5,
9319 6)))),
9320 b"...",
9321 []
9322 }
9323 b"rsLS_1ELS_1E..." => {
9324 Expression::Binary(OperatorName::Simple(SimpleOperatorName::Shr),
9325 Box::new(Expression::Primary(
9326 ExprPrimary::Literal(
9327 TypeHandle::BackReference(0),
9328 5,
9329 6))),
9330 Box::new(Expression::Primary(
9331 ExprPrimary::Literal(
9332 TypeHandle::BackReference(0),
9333 10,
9334 11)))),
9335 b"...",
9336 []
9337 }
9338 b"quLS_1ELS_2ELS_3E..." => {
9339 Expression::Ternary(OperatorName::Simple(SimpleOperatorName::Question),
9340 Box::new(Expression::Primary(
9341 ExprPrimary::Literal(
9342 TypeHandle::BackReference(0),
9343 5,
9344 6))),
9345 Box::new(Expression::Primary(
9346 ExprPrimary::Literal(
9347 TypeHandle::BackReference(0),
9348 10,
9349 11))),
9350 Box::new(Expression::Primary(
9351 ExprPrimary::Literal(
9352 TypeHandle::BackReference(0),
9353 15,
9354 16)))),
9355 b"...",
9356 []
9357 }
9358 b"pp_LS_1E..." => {
9359 Expression::PrefixInc(
9360 Box::new(Expression::Primary(
9361 ExprPrimary::Literal(
9362 TypeHandle::BackReference(0),
9363 6,
9364 7)))),
9365 b"...",
9366 []
9367 }
9368 b"mm_LS_1E..." => {
9369 Expression::PrefixDec(
9370 Box::new(Expression::Primary(
9371 ExprPrimary::Literal(
9372 TypeHandle::BackReference(0),
9373 6,
9374 7)))),
9375 b"...",
9376 []
9377 }
9378 b"clLS_1EE..." => {
9379 Expression::Call(
9380 Box::new(Expression::Primary(
9381 ExprPrimary::Literal(
9382 TypeHandle::BackReference(0),
9383 5,
9384 6))),
9385 vec![]),
9386 b"...",
9387 []
9388 }
9389 // ::= cv <type> <expression> # type (expression), conversion with one argument
9390 b"cvS_LS_1E..." => {
9391 Expression::ConversionOne(
9392 TypeHandle::BackReference(0),
9393 Box::new(Expression::Primary(
9394 ExprPrimary::Literal(
9395 TypeHandle::BackReference(0),
9396 7,
9397 8)))),
9398 b"...",
9399 []
9400 }
9401 b"cvS__LS_1ELS_1EE..." => {
9402 Expression::ConversionMany(
9403 TypeHandle::BackReference(0),
9404 vec![
9405 Expression::Primary(
9406 ExprPrimary::Literal(
9407 TypeHandle::BackReference(0),
9408 8,
9409 9)),
9410 Expression::Primary(
9411 ExprPrimary::Literal(
9412 TypeHandle::BackReference(0),
9413 13,
9414 14)),
9415 ]),
9416 b"...",
9417 []
9418 }
9419 b"tlS_LS_1ELS_1EE..." => {
9420 Expression::ConversionBraced(
9421 TypeHandle::BackReference(0),
9422 vec![
9423 Expression::Primary(
9424 ExprPrimary::Literal(
9425 TypeHandle::BackReference(0),
9426 7,
9427 8)),
9428 Expression::Primary(
9429 ExprPrimary::Literal(
9430 TypeHandle::BackReference(0),
9431 12,
9432 13)),
9433 ]),
9434 b"...",
9435 []
9436 }
9437 b"ilLS_1EE..." => {
9438 Expression::BracedInitList(
9439 Box::new(Expression::Primary(
9440 ExprPrimary::Literal(
9441 TypeHandle::BackReference(0),
9442 5,
9443 6)))),
9444 b"...",
9445 []
9446 }
9447 b"gsnwLS_1E_S_E..." => {
9448 Expression::GlobalNew(
9449 vec![
9450 Expression::Primary(
9451 ExprPrimary::Literal(
9452 TypeHandle::BackReference(0),
9453 7,
9454 8))
9455 ],
9456 TypeHandle::BackReference(0),
9457 None),
9458 b"...",
9459 []
9460 }
9461 b"nwLS_1E_S_E..." => {
9462 Expression::New(
9463 vec![
9464 Expression::Primary(
9465 ExprPrimary::Literal(
9466 TypeHandle::BackReference(0),
9467 5,
9468 6))
9469 ],
9470 TypeHandle::BackReference(0),
9471 None),
9472 b"...",
9473 []
9474 }
9475 b"gsnwLS_1E_S_piE..." => {
9476 Expression::GlobalNew(
9477 vec![
9478 Expression::Primary(
9479 ExprPrimary::Literal(
9480 TypeHandle::BackReference(0),
9481 7,
9482 8))
9483 ],
9484 TypeHandle::BackReference(0),
9485 Some(Initializer(vec![]))),
9486 b"...",
9487 []
9488 }
9489 b"nwLS_1E_S_piE..." => {
9490 Expression::New(
9491 vec![
9492 Expression::Primary(
9493 ExprPrimary::Literal(
9494 TypeHandle::BackReference(0),
9495 5,
9496 6))
9497 ],
9498 TypeHandle::BackReference(0),
9499 Some(Initializer(vec![]))),
9500 b"...",
9501 []
9502 }
9503 b"gsnaLS_1E_S_E..." => {
9504 Expression::GlobalNewArray(
9505 vec![
9506 Expression::Primary(
9507 ExprPrimary::Literal(
9508 TypeHandle::BackReference(0),
9509 7,
9510 8))
9511 ],
9512 TypeHandle::BackReference(0),
9513 None),
9514 b"...",
9515 []
9516 }
9517 b"naLS_1E_S_E..." => {
9518 Expression::NewArray(
9519 vec![
9520 Expression::Primary(
9521 ExprPrimary::Literal(
9522 TypeHandle::BackReference(0),
9523 5,
9524 6))
9525 ],
9526 TypeHandle::BackReference(0),
9527 None),
9528 b"...",
9529 []
9530 }
9531 b"gsnaLS_1E_S_piE..." => {
9532 Expression::GlobalNewArray(
9533 vec![
9534 Expression::Primary(
9535 ExprPrimary::Literal(
9536 TypeHandle::BackReference(0),
9537 7,
9538 8))
9539 ],
9540 TypeHandle::BackReference(0),
9541 Some(Initializer(vec![]))),
9542 b"...",
9543 []
9544 }
9545 b"naLS_1E_S_piE..." => {
9546 Expression::NewArray(
9547 vec![
9548 Expression::Primary(
9549 ExprPrimary::Literal(
9550 TypeHandle::BackReference(0),
9551 5,
9552 6))
9553 ],
9554 TypeHandle::BackReference(0),
9555 Some(Initializer(vec![]))),
9556 b"...",
9557 []
9558 }
9559 b"gsdlLS_1E..." => {
9560 Expression::GlobalDelete(
9561 Box::new(Expression::Primary(
9562 ExprPrimary::Literal(
9563 TypeHandle::BackReference(0),
9564 7,
9565 8)))),
9566 b"...",
9567 []
9568 }
9569 b"dlLS_1E..." => {
9570 Expression::Delete(
9571 Box::new(Expression::Primary(
9572 ExprPrimary::Literal(
9573 TypeHandle::BackReference(0),
9574 5,
9575 6)))),
9576 b"...",
9577 []
9578 }
9579 // ::= [gs] da <expression> # delete[] expression
9580 b"gsdaLS_1E..." => {
9581 Expression::GlobalDeleteArray(
9582 Box::new(Expression::Primary(
9583 ExprPrimary::Literal(
9584 TypeHandle::BackReference(0),
9585 7,
9586 8)))),
9587 b"...",
9588 []
9589 }
9590 b"daLS_1E..." => {
9591 Expression::DeleteArray(
9592 Box::new(Expression::Primary(
9593 ExprPrimary::Literal(
9594 TypeHandle::BackReference(0),
9595 5,
9596 6)))),
9597 b"...",
9598 []
9599 }
9600 b"dcS_LS_1E..." => {
9601 Expression::DynamicCast(
9602 TypeHandle::BackReference(0),
9603 Box::new(Expression::Primary(
9604 ExprPrimary::Literal(
9605 TypeHandle::BackReference(0),
9606 7,
9607 8)))),
9608 b"...",
9609 []
9610 }
9611 b"scS_LS_1E..." => {
9612 Expression::StaticCast(
9613 TypeHandle::BackReference(0),
9614 Box::new(Expression::Primary(
9615 ExprPrimary::Literal(
9616 TypeHandle::BackReference(0),
9617 7,
9618 8)))),
9619 b"...",
9620 []
9621 }
9622 b"ccS_LS_1E..." => {
9623 Expression::ConstCast(
9624 TypeHandle::BackReference(0),
9625 Box::new(Expression::Primary(
9626 ExprPrimary::Literal(
9627 TypeHandle::BackReference(0),
9628 7,
9629 8)))),
9630 b"...",
9631 []
9632 }
9633 b"rcS_LS_1E..." => {
9634 Expression::ReinterpretCast(
9635 TypeHandle::BackReference(0),
9636 Box::new(Expression::Primary(
9637 ExprPrimary::Literal(
9638 TypeHandle::BackReference(0),
9639 7,
9640 8)))),
9641 b"...",
9642 []
9643 }
9644 b"tiS_..." => {
9645 Expression::TypeidType(TypeHandle::BackReference(0)),
9646 b"...",
9647 []
9648 }
9649 b"teLS_1E..." => {
9650 Expression::TypeidExpr(
9651 Box::new(Expression::Primary(
9652 ExprPrimary::Literal(
9653 TypeHandle::BackReference(0),
9654 5,
9655 6)))),
9656 b"...",
9657 []
9658 }
9659 b"stS_..." => {
9660 Expression::SizeofType(TypeHandle::BackReference(0)),
9661 b"...",
9662 []
9663 }
9664 b"szLS_1E..." => {
9665 Expression::SizeofExpr(
9666 Box::new(Expression::Primary(
9667 ExprPrimary::Literal(
9668 TypeHandle::BackReference(0),
9669 5,
9670 6)))),
9671 b"...",
9672 []
9673 }
9674 b"atS_..." => {
9675 Expression::AlignofType(TypeHandle::BackReference(0)),
9676 b"...",
9677 []
9678 }
9679 b"azLS_1E..." => {
9680 Expression::AlignofExpr(
9681 Box::new(Expression::Primary(
9682 ExprPrimary::Literal(
9683 TypeHandle::BackReference(0),
9684 5,
9685 6)))),
9686 b"...",
9687 []
9688 }
9689 b"nxLS_1E..." => {
9690 Expression::Noexcept(
9691 Box::new(Expression::Primary(
9692 ExprPrimary::Literal(
9693 TypeHandle::BackReference(0),
9694 5,
9695 6)))),
9696 b"...",
9697 []
9698 }
9699 b"T_..." => {
9700 Expression::TemplateParam(TemplateParam(0)),
9701 b"...",
9702 []
9703 }
9704 b"fp_..." => {
9705 Expression::FunctionParam(FunctionParam(0, CvQualifiers::default(), Some(0))),
9706 b"...",
9707 []
9708 }
9709 b"dtT_3abc..." => {
9710 Expression::Member(
9711 Box::new(Expression::TemplateParam(TemplateParam(0))),
9712 MemberName(
9713 Name::Unscoped(
9714 UnscopedName::Unqualified(
9715 UnqualifiedName::Source(
9716 SourceName(
9717 Identifier {
9718 start: 5,
9719 end: 8,
9720 })))))),
9721 b"...",
9722 []
9723 }
9724 b"ptT_3abc..." => {
9725 Expression::DerefMember(
9726 Box::new(Expression::TemplateParam(TemplateParam(0))),
9727 MemberName(
9728 Name::Unscoped(
9729 UnscopedName::Unqualified(
9730 UnqualifiedName::Source(
9731 SourceName(
9732 Identifier {
9733 start: 5,
9734 end: 8,
9735 })))))),
9736 b"...",
9737 []
9738 }
9739 b"dtfp_clI3abcE..." => {
9740 Expression::Member(
9741 Box::new(Expression::FunctionParam(FunctionParam(0, CvQualifiers::default(), Some(0)))),
9742 MemberName(
9743 Name::UnscopedTemplate(
9744 UnscopedTemplateNameHandle::NonSubstitution(NonSubstitution(0)),
9745 TemplateArgs(vec![
9746 TemplateArg::Type(
9747 TypeHandle::BackReference(1))])))),
9748 b"...",
9749 [
9750 Substitutable::Type(
9751 Type::ClassEnum(
9752 ClassEnumType::Named(
9753 Name::Unscoped(
9754 UnscopedName::Unqualified(
9755 UnqualifiedName::Source(
9756 SourceName(
9757 Identifier {
9758 start: 9,
9759 end: 12
9760 })))))))
9761 ]
9762 }
9763 // ::= ds <expression> <expression> # expr.*expr
9764 b"dsT_T_..." => {
9765 Expression::PointerToMember(
9766 Box::new(Expression::TemplateParam(TemplateParam(0))),
9767 Box::new(Expression::TemplateParam(TemplateParam(0)))),
9768 b"...",
9769 []
9770 }
9771 b"sZT_..." => {
9772 Expression::SizeofTemplatePack(TemplateParam(0)),
9773 b"...",
9774 []
9775 }
9776 b"sZfp_..." => {
9777 Expression::SizeofFunctionPack(
9778 FunctionParam(0, CvQualifiers::default(), Some(0))),
9779 b"...",
9780 []
9781 }
9782 b"sPE..." => {
9783 Expression::SizeofCapturedTemplatePack(vec![]),
9784 b"...",
9785 []
9786 }
9787 b"spT_..." => {
9788 Expression::PackExpansion(
9789 Box::new(Expression::TemplateParam(TemplateParam(0)))),
9790 b"...",
9791 []
9792 }
9793 b"twT_..." => {
9794 Expression::Throw(Box::new(Expression::TemplateParam(TemplateParam(0)))),
9795 b"...",
9796 []
9797 }
9798 b"tr..." => {
9799 Expression::Rethrow,
9800 b"...",
9801 []
9802 }
9803 b"3abc..." => {
9804 Expression::UnresolvedName(
9805 UnresolvedName::Name(
9806 BaseUnresolvedName::Name(
9807 SimpleId(
9808 SourceName(Identifier {
9809 start: 1,
9810 end: 4,
9811 }),
9812 None)))),
9813 b"...",
9814 []
9815 }
9816 b"L_Z3abcE..." => {
9817 Expression::Primary(
9818 ExprPrimary::External(
9819 MangledName::Encoding(
9820 Encoding::Data(
9821 Name::Unscoped(
9822 UnscopedName::Unqualified(
9823 UnqualifiedName::Source(
9824 SourceName(Identifier {
9825 start: 4,
9826 end: 7,
9827 }))))), vec![]))),
9828 b"...",
9829 []
9830 }
9831 // An expression where arity matters
9832 b"cldtdefpT4TypeadsrT_5EnterE..." => {
9833 Expression::Call(
9834 Box::new(Expression::Member(
9835 Box::new(Expression::Unary(OperatorName::Simple(SimpleOperatorName::Deref),
9836 Box::new(Expression::FunctionParam(
9837 FunctionParam(0,
9838 CvQualifiers::default(),
9839 None)
9840 ))
9841 )),
9842 MemberName(
9843 Name::Unscoped(
9844 UnscopedName::Unqualified(
9845 UnqualifiedName::Source(
9846 SourceName(Identifier {
9847 start: 10,
9848 end: 14,
9849 })))
9850 )
9851 )
9852 )),
9853 vec![Expression::Unary(OperatorName::Simple(SimpleOperatorName::AddressOf),
9854 Box::new(Expression::UnresolvedName(
9855 UnresolvedName::Nested1(
9856 UnresolvedTypeHandle::BackReference(1),
9857 vec![],
9858 BaseUnresolvedName::Name(
9859 SimpleId(
9860 SourceName(Identifier {
9861 start: 21,
9862 end: 26
9863 }
9864 ),
9865 None
9866 )
9867 )
9868 ))))]
9869 ),
9870 b"...",
9871 [
9872 Substitutable::UnresolvedType(UnresolvedType::Template(TemplateParam(0), None))
9873 ]
9874 }
9875 }
9876 Err => {
9877 b"dtStfp_clI3abcE..." => Error::UnexpectedText,
9878 }
9879 }
9880 });
9881 }
9882
9883 #[test]
parse_unresolved_name()9884 fn parse_unresolved_name() {
9885 assert_parse!(UnresolvedName {
9886 with subs [
9887 Substitutable::UnresolvedType(
9888 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
9889 ] => {
9890 Ok => {
9891 b"gs3abc..." => {
9892 UnresolvedName::Global(BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
9893 start: 3,
9894 end: 6,
9895 }), None))),
9896 b"...",
9897 []
9898 }
9899 b"3abc..." => {
9900 UnresolvedName::Name(BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
9901 start: 1,
9902 end: 4,
9903 }), None))),
9904 b"...",
9905 []
9906 }
9907 b"srS_3abc..." => {
9908 UnresolvedName::Nested1(UnresolvedTypeHandle::BackReference(0),
9909 vec![],
9910 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
9911 start: 5,
9912 end: 8,
9913 }), None))),
9914 b"...",
9915 []
9916 }
9917 b"srNS_3abc3abcE3abc..." => {
9918 UnresolvedName::Nested1(
9919 UnresolvedTypeHandle::BackReference(0),
9920 vec![
9921 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
9922 start: 6,
9923 end: 9,
9924 }), None)),
9925 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
9926 start: 10,
9927 end: 13,
9928 }), None)),
9929 ],
9930 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
9931 start: 15,
9932 end: 18,
9933 }), None))),
9934 b"...",
9935 []
9936 }
9937 b"gssr3abcE3abc..." => {
9938 UnresolvedName::GlobalNested2(
9939 vec![
9940 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
9941 start: 5,
9942 end: 8,
9943 }), None)),
9944 ],
9945 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
9946 start: 10,
9947 end: 13,
9948 }), None))),
9949 b"...",
9950 []
9951 }
9952 b"sr3abcE3abc..." => {
9953 UnresolvedName::Nested2(
9954 vec![
9955 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
9956 start: 3,
9957 end: 6,
9958 }), None)),
9959 ],
9960 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
9961 start: 8,
9962 end: 11,
9963 }), None))),
9964 b"...",
9965 []
9966 }
9967 }
9968 Err => {
9969 b"zzzzzz" => Error::UnexpectedText,
9970 b"gszzz" => Error::UnexpectedText,
9971 b"gssrzzz" => Error::UnexpectedText,
9972 b"srNzzz" => Error::UnexpectedText,
9973 b"srzzz" => Error::UnexpectedText,
9974 b"srN3abczzzz" => Error::UnexpectedText,
9975 b"srN3abcE" => Error::UnexpectedText,
9976 b"srN3abc" => Error::UnexpectedText,
9977 b"srN" => Error::UnexpectedEnd,
9978 b"sr" => Error::UnexpectedEnd,
9979 b"gssr" => Error::UnexpectedEnd,
9980 b"gs" => Error::UnexpectedEnd,
9981 b"" => Error::UnexpectedEnd,
9982 }
9983 }
9984 });
9985 }
9986
9987 #[test]
parse_unresolved_type_handle()9988 fn parse_unresolved_type_handle() {
9989 assert_parse!(UnresolvedTypeHandle {
9990 with subs [
9991 Substitutable::UnresolvedType(
9992 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
9993 ] => {
9994 Ok => {
9995 b"S_..." => {
9996 UnresolvedTypeHandle::BackReference(0),
9997 b"...",
9998 []
9999 }
10000 b"T_..." => {
10001 UnresolvedTypeHandle::BackReference(1),
10002 b"...",
10003 [
10004 Substitutable::UnresolvedType(
10005 UnresolvedType::Template(TemplateParam(0), None)),
10006 ]
10007 }
10008 b"T_IS_E..." => {
10009 UnresolvedTypeHandle::BackReference(1),
10010 b"...",
10011 [
10012 Substitutable::UnresolvedType(
10013 UnresolvedType::Template(TemplateParam(0), Some(TemplateArgs(vec![
10014 TemplateArg::Type(TypeHandle::BackReference(0))
10015 ])))),
10016 ]
10017 }
10018 b"DTtrE..." => {
10019 UnresolvedTypeHandle::BackReference(1),
10020 b"...",
10021 [
10022 Substitutable::UnresolvedType(
10023 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow)))
10024 ]
10025
10026 }
10027 }
10028 Err => {
10029 b"zzzzzzz" => Error::UnexpectedText,
10030 b"" => Error::UnexpectedEnd,
10031 }
10032 }
10033 });
10034 }
10035
10036 #[test]
parse_unresolved_qualifier_level()10037 fn parse_unresolved_qualifier_level() {
10038 assert_parse!(UnresolvedQualifierLevel {
10039 with subs [
10040 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10041 ] => {
10042 Ok => {
10043 b"3abc..." => {
10044 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10045 start: 1,
10046 end: 4,
10047 }), None)),
10048 b"...",
10049 []
10050 }
10051 b"3abcIS_E..." => {
10052 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10053 start: 1,
10054 end: 4,
10055 }), Some(TemplateArgs(vec![
10056 TemplateArg::Type(TypeHandle::BackReference(0))
10057 ])))),
10058 b"...",
10059 []
10060 }
10061 }
10062 Err => {
10063 b"zzz" => Error::UnexpectedText,
10064 b"" => Error::UnexpectedEnd,
10065 }
10066 }
10067 });
10068 }
10069
10070 #[test]
parse_simple_id()10071 fn parse_simple_id() {
10072 assert_parse!(SimpleId {
10073 with subs [
10074 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10075 ] => {
10076 Ok => {
10077 b"3abc..." => {
10078 SimpleId(SourceName(Identifier {
10079 start: 1,
10080 end: 4,
10081 }), None),
10082 b"...",
10083 []
10084 }
10085 b"3abcIS_E..." => {
10086 SimpleId(SourceName(Identifier {
10087 start: 1,
10088 end: 4,
10089 }), Some(TemplateArgs(vec![
10090 TemplateArg::Type(TypeHandle::BackReference(0))
10091 ]))),
10092 b"...",
10093 []
10094 }
10095 }
10096 Err => {
10097 b"zzz" => Error::UnexpectedText,
10098 b"" => Error::UnexpectedEnd,
10099 }
10100 }
10101 });
10102 }
10103
10104 #[test]
parse_base_unresolved_name()10105 fn parse_base_unresolved_name() {
10106 assert_parse!(BaseUnresolvedName {
10107 with subs [
10108 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10109 ] => {
10110 Ok => {
10111 b"3abc..." => {
10112 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10113 start: 1,
10114 end: 4,
10115 }), None)),
10116 b"...",
10117 []
10118 }
10119 b"onnw..." => {
10120 BaseUnresolvedName::Operator(OperatorName::Simple(SimpleOperatorName::New), None),
10121 b"...",
10122 []
10123 }
10124 b"onnwIS_E..." => {
10125 BaseUnresolvedName::Operator(OperatorName::Simple(SimpleOperatorName::New),
10126 Some(TemplateArgs(vec![
10127 TemplateArg::Type(TypeHandle::BackReference(0))
10128 ]))),
10129 b"...",
10130 []
10131 }
10132 b"dn3abc..." => {
10133 BaseUnresolvedName::Destructor(DestructorName::Name(SimpleId(SourceName(Identifier {
10134 start: 3,
10135 end: 6,
10136 }), None))),
10137 b"...",
10138 []
10139 }
10140 }
10141 Err => {
10142 b"ozzz" => Error::UnexpectedText,
10143 b"dzzz" => Error::UnexpectedText,
10144 b"dn" => Error::UnexpectedEnd,
10145 b"on" => Error::UnexpectedEnd,
10146 b"" => Error::UnexpectedEnd,
10147 }
10148 }
10149 });
10150 }
10151
10152 #[test]
parse_destructor_name()10153 fn parse_destructor_name() {
10154 assert_parse!(DestructorName {
10155 with subs [
10156 Substitutable::UnresolvedType(
10157 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
10158 ] => {
10159 Ok => {
10160 b"S_..." => {
10161 DestructorName::Unresolved(UnresolvedTypeHandle::BackReference(0)),
10162 b"...",
10163 []
10164 }
10165 b"3abc..." => {
10166 DestructorName::Name(SimpleId(SourceName(Identifier {
10167 start: 1,
10168 end: 4,
10169 }), None)),
10170 b"...",
10171 []
10172 }
10173 }
10174 Err => {
10175 b"zzz" => Error::UnexpectedText,
10176 b"" => Error::UnexpectedEnd,
10177 }
10178 }
10179 });
10180 }
10181
10182 #[test]
parse_expr_primary()10183 fn parse_expr_primary() {
10184 assert_parse!(ExprPrimary {
10185 with subs [
10186 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10187 ] => {
10188 Ok => {
10189 b"LS_12345E..." => {
10190 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 8),
10191 b"...",
10192 []
10193 }
10194 b"LS_E..." => {
10195 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 3),
10196 b"...",
10197 []
10198 }
10199 b"L_Z3abcE..." => {
10200 ExprPrimary::External(
10201 MangledName::Encoding(
10202 Encoding::Data(
10203 Name::Unscoped(
10204 UnscopedName::Unqualified(
10205 UnqualifiedName::Source(
10206 SourceName(Identifier {
10207 start: 4,
10208 end: 7,
10209 }))))), vec![])),
10210 b"...",
10211 []
10212 }
10213 }
10214 Err => {
10215 b"zzz" => Error::UnexpectedText,
10216 b"LS_zzz" => Error::UnexpectedEnd,
10217 b"LS_12345" => Error::UnexpectedEnd,
10218 b"LS_" => Error::UnexpectedEnd,
10219 b"L" => Error::UnexpectedEnd,
10220 b"" => Error::UnexpectedEnd,
10221 }
10222 }
10223 });
10224 }
10225
10226 #[test]
parse_initializer()10227 fn parse_initializer() {
10228 assert_parse!(Initializer {
10229 Ok => {
10230 b"piE..." => {
10231 Initializer(vec![]),
10232 b"..."
10233 }
10234 b"pitrtrtrE..." => {
10235 Initializer(vec![
10236 Expression::Rethrow,
10237 Expression::Rethrow,
10238 Expression::Rethrow,
10239 ]),
10240 b"..."
10241 }
10242 }
10243 Err => {
10244 b"pirtrtrt..." => Error::UnexpectedText,
10245 b"pi..." => Error::UnexpectedText,
10246 b"..." => Error::UnexpectedText,
10247 b"pirt" => Error::UnexpectedText,
10248 b"pi" => Error::UnexpectedEnd,
10249 b"p" => Error::UnexpectedEnd,
10250 b"" => Error::UnexpectedEnd,
10251 }
10252 });
10253 }
10254
10255 #[test]
parse_local_name()10256 fn parse_local_name() {
10257 assert_parse!(LocalName {
10258 Ok => {
10259 b"Z3abcE3def_0..." => {
10260 LocalName::Relative(
10261 Box::new(Encoding::Data(
10262 Name::Unscoped(
10263 UnscopedName::Unqualified(
10264 UnqualifiedName::Source(
10265 SourceName(Identifier {
10266 start: 2,
10267 end: 5,
10268 })))))),
10269 Some(Box::new(Name::Unscoped(
10270 UnscopedName::Unqualified(
10271 UnqualifiedName::Source(
10272 SourceName(Identifier {
10273 start: 7,
10274 end: 10,
10275 })))))),
10276 Some(Discriminator(0))),
10277 b"..."
10278 }
10279 b"Z3abcE3def..." => {
10280 LocalName::Relative(
10281 Box::new(Encoding::Data(
10282 Name::Unscoped(
10283 UnscopedName::Unqualified(
10284 UnqualifiedName::Source(
10285 SourceName(Identifier {
10286 start: 2,
10287 end: 5,
10288 })))))),
10289 Some(Box::new(Name::Unscoped(
10290 UnscopedName::Unqualified(
10291 UnqualifiedName::Source(
10292 SourceName(Identifier {
10293 start: 7,
10294 end: 10,
10295 })))))),
10296 None),
10297 b"..."
10298 }
10299 b"Z3abcEs_0..." => {
10300 LocalName::Relative(
10301 Box::new(Encoding::Data(
10302 Name::Unscoped(
10303 UnscopedName::Unqualified(
10304 UnqualifiedName::Source(
10305 SourceName(Identifier {
10306 start: 2,
10307 end: 5,
10308 })))))),
10309 None,
10310 Some(Discriminator(0))),
10311 b"..."
10312 }
10313 b"Z3abcEs..." => {
10314 LocalName::Relative(
10315 Box::new(Encoding::Data(
10316 Name::Unscoped(
10317 UnscopedName::Unqualified(
10318 UnqualifiedName::Source(
10319 SourceName(Identifier {
10320 start: 2,
10321 end: 5,
10322 })))))),
10323 None,
10324 None),
10325 b"..."
10326 }
10327 b"Z3abcEd1_3abc..." => {
10328 LocalName::Default(
10329 Box::new(Encoding::Data(
10330 Name::Unscoped(
10331 UnscopedName::Unqualified(
10332 UnqualifiedName::Source(
10333 SourceName(Identifier {
10334 start: 2,
10335 end: 5,
10336 })))))),
10337 Some(1),
10338 Box::new(Name::Unscoped(
10339 UnscopedName::Unqualified(
10340 UnqualifiedName::Source(
10341 SourceName(Identifier {
10342 start: 10,
10343 end: 13,
10344 })))))),
10345 b"..."
10346 }
10347 b"Z3abcEd_3abc..." => {
10348 LocalName::Default(
10349 Box::new(Encoding::Data(
10350 Name::Unscoped(
10351 UnscopedName::Unqualified(
10352 UnqualifiedName::Source(
10353 SourceName(Identifier {
10354 start: 2,
10355 end: 5,
10356 })))))),
10357 None,
10358 Box::new(Name::Unscoped(
10359 UnscopedName::Unqualified(
10360 UnqualifiedName::Source(
10361 SourceName(Identifier {
10362 start: 9,
10363 end: 12,
10364 })))))),
10365 b"..."
10366 }
10367 }
10368 Err => {
10369 b"A" => Error::UnexpectedText,
10370 b"Z1a" => Error::UnexpectedEnd,
10371 b"Z1aE" => Error::UnexpectedEnd,
10372 b"Z" => Error::UnexpectedEnd,
10373 b"" => Error::UnexpectedEnd,
10374 }
10375 });
10376 }
10377
10378 #[test]
parse_closure_type_name()10379 fn parse_closure_type_name() {
10380 assert_parse!(ClosureTypeName {
10381 Ok => {
10382 b"UlvE_..." => {
10383 ClosureTypeName(LambdaSig(vec![]), None),
10384 b"..."
10385 }
10386 b"UlvE36_..." => {
10387 ClosureTypeName(LambdaSig(vec![]), Some(36)),
10388 b"..."
10389 }
10390 }
10391 Err => {
10392 b"UlvE36zzz" => Error::UnexpectedText,
10393 b"UlvEzzz" => Error::UnexpectedText,
10394 b"Ulvzzz" => Error::UnexpectedText,
10395 b"zzz" => Error::UnexpectedText,
10396 b"UlvE10" => Error::UnexpectedEnd,
10397 b"UlvE" => Error::UnexpectedEnd,
10398 b"Ulv" => Error::UnexpectedEnd,
10399 b"Ul" => Error::UnexpectedEnd,
10400 b"U" => Error::UnexpectedEnd,
10401 b"" => Error::UnexpectedEnd,
10402 }
10403 });
10404 }
10405
10406 #[test]
parse_lambda_sig()10407 fn parse_lambda_sig() {
10408 assert_parse!(LambdaSig {
10409 with subs [
10410 Substitutable::Type(
10411 Type::PointerTo(
10412 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Bool))))
10413 ] => {
10414 Ok => {
10415 b"v..." => {
10416 LambdaSig(vec![]),
10417 b"...",
10418 []
10419 }
10420 b"S_S_S_..." => {
10421 LambdaSig(vec![
10422 TypeHandle::BackReference(0),
10423 TypeHandle::BackReference(0),
10424 TypeHandle::BackReference(0),
10425 ]),
10426 b"...",
10427 []
10428 }
10429 }
10430 Err => {
10431 b"..." => Error::UnexpectedText,
10432 b"S" => Error::UnexpectedEnd,
10433 b"" => Error::UnexpectedEnd,
10434 }
10435 }
10436 });
10437 }
10438
10439 #[test]
parse_substitution()10440 fn parse_substitution() {
10441 assert_parse!(Substitution {
10442 with subs [
10443 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow))),
10444 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow))),
10445 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10446 ] => {
10447 Ok => {
10448 b"S_..." => {
10449 Substitution::BackReference(0),
10450 b"...",
10451 []
10452 }
10453 b"S1_..." => {
10454 Substitution::BackReference(2),
10455 b"...",
10456 []
10457 }
10458 b"St..." => {
10459 Substitution::WellKnown(WellKnownComponent::Std),
10460 b"...",
10461 []
10462 }
10463 b"Sa..." => {
10464 Substitution::WellKnown(WellKnownComponent::StdAllocator),
10465 b"...",
10466 []
10467 }
10468 b"Sb..." => {
10469 Substitution::WellKnown(WellKnownComponent::StdString1),
10470 b"...",
10471 []
10472 }
10473 b"Ss..." => {
10474 Substitution::WellKnown(WellKnownComponent::StdString2),
10475 b"...",
10476 []
10477 }
10478 b"Si..." => {
10479 Substitution::WellKnown(WellKnownComponent::StdIstream),
10480 b"...",
10481 []
10482 }
10483 b"So..." => {
10484 Substitution::WellKnown(WellKnownComponent::StdOstream),
10485 b"...",
10486 []
10487 }
10488 b"Sd..." => {
10489 Substitution::WellKnown(WellKnownComponent::StdIostream),
10490 b"...",
10491 []
10492 }
10493 }
10494 Err => {
10495 b"S999_" => Error::BadBackReference,
10496 b"Sz" => Error::UnexpectedText,
10497 b"zzz" => Error::UnexpectedText,
10498 b"S1" => Error::UnexpectedEnd,
10499 b"S" => Error::UnexpectedEnd,
10500 b"" => Error::UnexpectedEnd,
10501 }
10502 }
10503 });
10504 }
10505
10506 #[test]
parse_special_name()10507 fn parse_special_name() {
10508 assert_parse!(SpecialName {
10509 Ok => {
10510 b"TVi..." => {
10511 SpecialName::VirtualTable(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10512 b"..."
10513 }
10514 b"TTi..." => {
10515 SpecialName::Vtt(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10516 b"..."
10517 }
10518 b"TIi..." => {
10519 SpecialName::Typeinfo(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10520 b"..."
10521 }
10522 b"TSi..." => {
10523 SpecialName::TypeinfoName(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10524 b"..."
10525 }
10526 b"Tv42_36_3abc..." => {
10527 SpecialName::VirtualOverrideThunk(
10528 CallOffset::Virtual(VOffset(42, 36)),
10529 Box::new(Encoding::Data(
10530 Name::Unscoped(
10531 UnscopedName::Unqualified(
10532 UnqualifiedName::Source(
10533 SourceName(Identifier {
10534 start: 9,
10535 end: 12,
10536 }))))))),
10537 b"..."
10538 }
10539 b"Tcv42_36_v42_36_3abc..." => {
10540 SpecialName::VirtualOverrideThunkCovariant(
10541 CallOffset::Virtual(VOffset(42, 36)),
10542 CallOffset::Virtual(VOffset(42, 36)),
10543 Box::new(Encoding::Data(
10544 Name::Unscoped(
10545 UnscopedName::Unqualified(
10546 UnqualifiedName::Source(
10547 SourceName(Identifier {
10548 start: 17,
10549 end: 20,
10550 }))))))),
10551 b"..."
10552 }
10553 b"GV3abc..." => {
10554 SpecialName::Guard(
10555 Name::Unscoped(
10556 UnscopedName::Unqualified(
10557 UnqualifiedName::Source(
10558 SourceName(Identifier {
10559 start: 3,
10560 end: 6,
10561 }))))),
10562 b"..."
10563 }
10564 b"GR3abc_..." => {
10565 SpecialName::GuardTemporary(
10566 Name::Unscoped(
10567 UnscopedName::Unqualified(
10568 UnqualifiedName::Source(
10569 SourceName(Identifier {
10570 start: 3,
10571 end: 6,
10572 })))),
10573 0),
10574 b"..."
10575 }
10576 b"GR3abc0_..." => {
10577 SpecialName::GuardTemporary(
10578 Name::Unscoped(
10579 UnscopedName::Unqualified(
10580 UnqualifiedName::Source(
10581 SourceName(Identifier {
10582 start: 3,
10583 end: 6,
10584 })))),
10585 1),
10586 b"..."
10587 }
10588 b"Gr4_abc..." => {
10589 SpecialName::JavaResource(vec![ResourceName {
10590 start: 4,
10591 end: 7,
10592 }]),
10593 b"..."
10594 }
10595 b"TCc7_i..." => {
10596 SpecialName::ConstructionVtable(
10597 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)),
10598 7,
10599 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))
10600 ),
10601 b"..."
10602 }
10603 b"TFi..." => {
10604 SpecialName::TypeinfoFunction(
10605 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10606 b"..."
10607 }
10608 b"TH4name..." => {
10609 SpecialName::TlsInit(
10610 Name::Unscoped(
10611 UnscopedName::Unqualified(
10612 UnqualifiedName::Source(
10613 SourceName(Identifier { start: 3, end: 7 }))))),
10614 b"..."
10615 }
10616 b"TW4name..." => {
10617 SpecialName::TlsWrapper(
10618 Name::Unscoped(
10619 UnscopedName::Unqualified(
10620 UnqualifiedName::Source(
10621 SourceName(Identifier { start: 3, end: 7 }))))),
10622 b"..."
10623 }
10624 }
10625 Err => {
10626 b"TZ" => Error::UnexpectedText,
10627 b"GZ" => Error::UnexpectedText,
10628 b"GR3abcz" => Error::UnexpectedText,
10629 b"GR3abc0z" => Error::UnexpectedText,
10630 b"T" => Error::UnexpectedEnd,
10631 b"G" => Error::UnexpectedEnd,
10632 b"" => Error::UnexpectedEnd,
10633 b"GR3abc" => Error::UnexpectedEnd,
10634 b"GR3abc0" => Error::UnexpectedEnd,
10635 // This number is not allowed to be negative.
10636 b"TCcn7_i..." => Error::UnexpectedText,
10637 b"Gr3abc0" => Error::UnexpectedText,
10638 }
10639 });
10640 }
10641
10642 #[test]
parse_function_param()10643 fn parse_function_param() {
10644 assert_parse!(FunctionParam {
10645 Ok => {
10646 b"fpK_..." => {
10647 FunctionParam(0,
10648 CvQualifiers {
10649 restrict: false,
10650 volatile: false,
10651 const_: true,
10652 },
10653 Some(0)),
10654 b"..."
10655 }
10656 b"fL1pK_..." => {
10657 FunctionParam(1,
10658 CvQualifiers {
10659 restrict: false,
10660 volatile: false,
10661 const_: true,
10662 },
10663 Some(0)),
10664 b"..."
10665 }
10666 b"fpK3_..." => {
10667 FunctionParam(0,
10668 CvQualifiers {
10669 restrict: false,
10670 volatile: false,
10671 const_: true,
10672 },
10673 Some(4)),
10674 b"..."
10675 }
10676 b"fL1pK4_..." => {
10677 FunctionParam(1,
10678 CvQualifiers {
10679 restrict: false,
10680 volatile: false,
10681 const_: true,
10682 },
10683 Some(5)),
10684 b"..."
10685 }
10686 }
10687 Err => {
10688 b"fz" => Error::UnexpectedText,
10689 b"fLp_" => Error::UnexpectedText,
10690 b"fpL_" => Error::UnexpectedText,
10691 b"fL1pK4z" => Error::UnexpectedText,
10692 b"fL1pK4" => Error::UnexpectedEnd,
10693 b"fL1p" => Error::UnexpectedEnd,
10694 b"fL1" => Error::UnexpectedEnd,
10695 b"fL" => Error::UnexpectedEnd,
10696 b"f" => Error::UnexpectedEnd,
10697 b"" => Error::UnexpectedEnd,
10698 }
10699 });
10700 }
10701
10702 #[test]
parse_discriminator()10703 fn parse_discriminator() {
10704 assert_parse!(Discriminator {
10705 Ok => {
10706 b"_0..." => {
10707 Discriminator(0),
10708 b"..."
10709 }
10710 b"_9..." => {
10711 Discriminator(9),
10712 b"..."
10713 }
10714 b"__99_..." => {
10715 Discriminator(99),
10716 b"..."
10717 }
10718 }
10719 Err => {
10720 b"_n1" => Error::UnexpectedText,
10721 b"__99..." => Error::UnexpectedText,
10722 b"__99" => Error::UnexpectedEnd,
10723 b"..." => Error::UnexpectedText,
10724 }
10725 });
10726 }
10727
10728 #[test]
parse_data_member_prefix()10729 fn parse_data_member_prefix() {
10730 assert_parse!(DataMemberPrefix {
10731 Ok => {
10732 b"3fooM..." => {
10733 DataMemberPrefix(SourceName(Identifier {
10734 start: 1,
10735 end: 4,
10736 })),
10737 b"..."
10738 }
10739 }
10740 Err => {
10741 b"zzz" => Error::UnexpectedText,
10742 b"1" => Error::UnexpectedEnd,
10743 b"" => Error::UnexpectedEnd,
10744 }
10745 });
10746 }
10747
10748 #[test]
parse_ref_qualifier()10749 fn parse_ref_qualifier() {
10750 assert_parse!(RefQualifier {
10751 Ok => {
10752 b"R..." => {
10753 RefQualifier::LValueRef,
10754 b"..."
10755 }
10756 b"O..." => {
10757 RefQualifier::RValueRef,
10758 b"..."
10759 }
10760 }
10761 Err => {
10762 b"..." => Error::UnexpectedText,
10763 b"" => Error::UnexpectedEnd,
10764 }
10765 });
10766 }
10767
10768 #[test]
parse_cv_qualifiers()10769 fn parse_cv_qualifiers() {
10770 assert_parse!(CvQualifiers {
10771 Ok => {
10772 b"" => {
10773 CvQualifiers { restrict: false, volatile: false, const_: false },
10774 b""
10775 }
10776 b"..." => {
10777 CvQualifiers { restrict: false, volatile: false, const_: false },
10778 b"..."
10779 }
10780 b"r..." => {
10781 CvQualifiers { restrict: true, volatile: false, const_: false },
10782 b"..."
10783 }
10784 b"rV..." => {
10785 CvQualifiers { restrict: true, volatile: true, const_: false },
10786 b"..."
10787 }
10788 b"rVK..." => {
10789 CvQualifiers { restrict: true, volatile: true, const_: true },
10790 b"..."
10791 }
10792 b"V" => {
10793 CvQualifiers { restrict: false, volatile: true, const_: false },
10794 b""
10795 }
10796 b"VK" => {
10797 CvQualifiers { restrict: false, volatile: true, const_: true },
10798 b""
10799 }
10800 b"K..." => {
10801 CvQualifiers { restrict: false, volatile: false, const_: true },
10802 b"..."
10803 }
10804 }
10805 Err => {
10806 // None.
10807 }
10808 });
10809 }
10810
10811 #[test]
parse_builtin_type()10812 fn parse_builtin_type() {
10813 assert_parse!(BuiltinType {
10814 Ok => {
10815 b"c..." => {
10816 BuiltinType::Standard(StandardBuiltinType::Char),
10817 b"..."
10818 }
10819 b"c" => {
10820 BuiltinType::Standard(StandardBuiltinType::Char),
10821 b""
10822 }
10823 b"u3abc..." => {
10824 BuiltinType::Extension(SourceName(Identifier {
10825 start: 2,
10826 end: 5,
10827 })),
10828 b"..."
10829 }
10830 }
10831 Err => {
10832 b"." => Error::UnexpectedText,
10833 b"" => Error::UnexpectedEnd,
10834 }
10835 });
10836 }
10837
10838 #[test]
parse_template_param()10839 fn parse_template_param() {
10840 assert_parse!(TemplateParam {
10841 Ok => {
10842 b"T_..." => {
10843 TemplateParam(0),
10844 b"..."
10845 }
10846 b"T3_..." => {
10847 TemplateParam(4),
10848 b"..."
10849 }
10850 }
10851 Err => {
10852 b"wtf" => Error::UnexpectedText,
10853 b"Twtf" => Error::UnexpectedText,
10854 b"T3wtf" => Error::UnexpectedText,
10855 b"T" => Error::UnexpectedEnd,
10856 b"T3" => Error::UnexpectedEnd,
10857 b"" => Error::UnexpectedEnd,
10858 }
10859 });
10860 }
10861
10862 #[test]
parse_unscoped_name()10863 fn parse_unscoped_name() {
10864 assert_parse!(UnscopedName {
10865 Ok => {
10866 b"St5hello..." => {
10867 UnscopedName::Std(UnqualifiedName::Source(SourceName(Identifier {
10868 start: 3,
10869 end: 8,
10870 }))),
10871 b"..."
10872 }
10873 b"5hello..." => {
10874 UnscopedName::Unqualified(UnqualifiedName::Source(SourceName(Identifier {
10875 start: 1,
10876 end: 6,
10877 }))),
10878 b"..."
10879 }
10880 }
10881 Err => {
10882 b"St..." => Error::UnexpectedText,
10883 b"..." => Error::UnexpectedText,
10884 b"" => Error::UnexpectedEnd,
10885 }
10886 });
10887 }
10888
10889 #[test]
parse_unqualified_name()10890 fn parse_unqualified_name() {
10891 assert_parse!(UnqualifiedName {
10892 Ok => {
10893 b"qu.." => {
10894 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::Question)),
10895 b".."
10896 }
10897 b"C1.." => {
10898 UnqualifiedName::CtorDtor(CtorDtorName::CompleteConstructor(None)),
10899 b".."
10900 }
10901 b"10abcdefghij..." => {
10902 UnqualifiedName::Source(SourceName(Identifier {
10903 start: 2,
10904 end: 12,
10905 })),
10906 b"..."
10907 }
10908 b"UllE_..." => {
10909 UnqualifiedName::ClosureType(
10910 ClosureTypeName(
10911 LambdaSig(vec![
10912 TypeHandle::Builtin(
10913 BuiltinType::Standard(
10914 StandardBuiltinType::Long))
10915 ]),
10916 None)),
10917 b"..."
10918 }
10919 b"Ut5_..." => {
10920 UnqualifiedName::UnnamedType(UnnamedTypeName(Some(5))),
10921 b"..."
10922 }
10923 b"B5cxx11..." => {
10924 UnqualifiedName::ABITag(TaggedName(SourceName(Identifier {
10925 start: 2,
10926 end: 7,
10927 }))),
10928 b"..."
10929 }
10930 b"L3foo_0..." => {
10931 UnqualifiedName::LocalSourceName(
10932 SourceName(Identifier {
10933 start: 2,
10934 end: 5
10935 }),
10936 Some(Discriminator(0))
10937 ),
10938 "..."
10939 }
10940 b"L3foo..." => {
10941 UnqualifiedName::LocalSourceName(
10942 SourceName(Identifier {
10943 start: 2,
10944 end: 5
10945 }),
10946 None
10947 ),
10948 "..."
10949 }
10950 }
10951 Err => {
10952 b"zzz" => Error::UnexpectedText,
10953 b"Uq" => Error::UnexpectedText,
10954 b"C" => Error::UnexpectedEnd,
10955 b"" => Error::UnexpectedEnd,
10956 }
10957 });
10958 }
10959
10960 #[test]
parse_unnamed_type_name()10961 fn parse_unnamed_type_name() {
10962 assert_parse!(UnnamedTypeName {
10963 Ok => {
10964 b"Ut_abc" => {
10965 UnnamedTypeName(None),
10966 b"abc"
10967 }
10968 b"Ut42_abc" => {
10969 UnnamedTypeName(Some(42)),
10970 b"abc"
10971 }
10972 b"Ut42_" => {
10973 UnnamedTypeName(Some(42)),
10974 b""
10975 }
10976 }
10977 Err => {
10978 b"ut_" => Error::UnexpectedText,
10979 b"u" => Error::UnexpectedEnd,
10980 b"Ut" => Error::UnexpectedEnd,
10981 b"Ut._" => Error::UnexpectedText,
10982 b"Ut42" => Error::UnexpectedEnd,
10983 }
10984 });
10985 }
10986
10987 #[test]
parse_identifier()10988 fn parse_identifier() {
10989 assert_parse!(Identifier {
10990 Ok => {
10991 b"1abc" => {
10992 Identifier { start: 0, end: 4 },
10993 b""
10994 }
10995 b"_Az1\0\0\0" => {
10996 Identifier { start: 0, end: 4 },
10997 b"\0\0\0"
10998 }
10999 b"$_0\0\0\0" => {
11000 Identifier { start: 0, end: 3 },
11001 b"\0\0\0"
11002 }
11003 }
11004 Err => {
11005 b"\0\0\0" => Error::UnexpectedText,
11006 b"" => Error::UnexpectedEnd,
11007 }
11008 });
11009 }
11010
11011 #[test]
parse_source_name()11012 fn parse_source_name() {
11013 assert_parse!(SourceName {
11014 Ok => {
11015 b"1abc" => {
11016 SourceName(Identifier { start: 1, end: 2 }),
11017 b"bc"
11018 }
11019 b"10abcdefghijklm" => {
11020 SourceName(Identifier { start: 2, end: 12 }),
11021 b"klm"
11022 }
11023 }
11024 Err => {
11025 b"0abc" => Error::UnexpectedText,
11026 b"n1abc" => Error::UnexpectedText,
11027 b"10abcdef" => Error::UnexpectedEnd,
11028 b"" => Error::UnexpectedEnd,
11029 }
11030 });
11031 }
11032
11033 #[test]
parse_number()11034 fn parse_number() {
11035 assert_parse!(Number {
11036 Ok => {
11037 b"n2n3" => {
11038 -2,
11039 b"n3"
11040 }
11041 b"12345abcdef" => {
11042 12345,
11043 b"abcdef"
11044 }
11045 b"0abcdef" => {
11046 0,
11047 b"abcdef"
11048 }
11049 b"42" => {
11050 42,
11051 b""
11052 }
11053 }
11054 Err => {
11055 b"001" => Error::UnexpectedText,
11056 b"wutang" => Error::UnexpectedText,
11057 b"n" => Error::UnexpectedEnd,
11058 b"" => Error::UnexpectedEnd,
11059 }
11060 });
11061 }
11062
11063 #[test]
parse_call_offset()11064 fn parse_call_offset() {
11065 assert_parse!(CallOffset {
11066 Ok => {
11067 b"hn42_..." => {
11068 CallOffset::NonVirtual(NvOffset(-42)),
11069 b"..."
11070 }
11071 b"vn42_36_..." => {
11072 CallOffset::Virtual(VOffset(-42, 36)),
11073 b"..."
11074 }
11075 }
11076 Err => {
11077 b"h1..." => Error::UnexpectedText,
11078 b"v1_1..." => Error::UnexpectedText,
11079 b"hh" => Error::UnexpectedText,
11080 b"vv" => Error::UnexpectedText,
11081 b"z" => Error::UnexpectedText,
11082 b"" => Error::UnexpectedEnd,
11083 }
11084 });
11085 }
11086
11087 #[test]
parse_v_offset()11088 fn parse_v_offset() {
11089 assert_parse!(VOffset {
11090 Ok => {
11091 b"n2_n3abcdef" => {
11092 VOffset(-2, -3),
11093 b"abcdef"
11094 }
11095 b"12345_12345abcdef" => {
11096 VOffset(12345, 12345),
11097 b"abcdef"
11098 }
11099 b"0_0abcdef" => {
11100 VOffset(0, 0),
11101 b"abcdef"
11102 }
11103 b"42_n3" => {
11104 VOffset(42, -3),
11105 b""
11106 }
11107 }
11108 Err => {
11109 b"001" => Error::UnexpectedText,
11110 b"1_001" => Error::UnexpectedText,
11111 b"wutang" => Error::UnexpectedText,
11112 b"n_" => Error::UnexpectedText,
11113 b"1_n" => Error::UnexpectedEnd,
11114 b"1_" => Error::UnexpectedEnd,
11115 b"n" => Error::UnexpectedEnd,
11116 b"" => Error::UnexpectedEnd,
11117 }
11118 });
11119 }
11120
11121 #[test]
parse_nv_offset()11122 fn parse_nv_offset() {
11123 assert_parse!(NvOffset {
11124 Ok => {
11125 b"n2n3" => {
11126 NvOffset(-2),
11127 b"n3"
11128 }
11129 b"12345abcdef" => {
11130 NvOffset(12345),
11131 b"abcdef"
11132 }
11133 b"0abcdef" => {
11134 NvOffset(0),
11135 b"abcdef"
11136 }
11137 b"42" => {
11138 NvOffset(42),
11139 b""
11140 }
11141 }
11142 Err => {
11143 b"001" => Error::UnexpectedText,
11144 b"wutang" => Error::UnexpectedText,
11145 b"" => Error::UnexpectedEnd,
11146 }
11147 });
11148 }
11149
11150 #[test]
parse_seq_id()11151 fn parse_seq_id() {
11152 assert_parse!(SeqId {
11153 Ok => {
11154 b"1_" => {
11155 SeqId(1),
11156 b"_"
11157 }
11158 b"42" => {
11159 SeqId(146),
11160 b""
11161 }
11162 b"ABCabc" => {
11163 SeqId(13368),
11164 b"abc"
11165 }
11166 }
11167 Err => {
11168 b"abc" => Error::UnexpectedText,
11169 b"001" => Error::UnexpectedText,
11170 b"wutang" => Error::UnexpectedText,
11171 b"" => Error::UnexpectedEnd,
11172 }
11173 });
11174 }
11175
11176 #[test]
parse_ctor_dtor_name()11177 fn parse_ctor_dtor_name() {
11178 assert_parse!(CtorDtorName {
11179 Ok => {
11180 b"D0" => {
11181 CtorDtorName::DeletingDestructor,
11182 b""
11183 }
11184 b"C101" => {
11185 CtorDtorName::CompleteConstructor(None),
11186 b"01"
11187 }
11188 }
11189 Err => {
11190 b"gayagaya" => Error::UnexpectedText,
11191 b"C" => Error::UnexpectedEnd,
11192 b"" => Error::UnexpectedEnd,
11193 }
11194 });
11195 }
11196
11197 #[test]
parse_operator_name()11198 fn parse_operator_name() {
11199 assert_parse!(OperatorName {
11200 Ok => {
11201 b"qu..." => {
11202 OperatorName::Simple(SimpleOperatorName::Question),
11203 b"..."
11204 }
11205 b"cvi..." => {
11206 OperatorName::Conversion(
11207 TypeHandle::Builtin(
11208 BuiltinType::Standard(
11209 StandardBuiltinType::Int))),
11210 b"..."
11211 }
11212 b"li3Foo..." => {
11213 OperatorName::Literal(SourceName(Identifier {
11214 start: 3,
11215 end: 6,
11216 })),
11217 b"..."
11218 }
11219 b"v33Foo..." => {
11220 OperatorName::VendorExtension(3, SourceName(Identifier {
11221 start: 3,
11222 end: 6
11223 })),
11224 b"..."
11225 }
11226 }
11227 Err => {
11228 b"cv" => Error::UnexpectedEnd,
11229 b"li3ab" => Error::UnexpectedEnd,
11230 b"li" => Error::UnexpectedEnd,
11231 b"v33ab" => Error::UnexpectedEnd,
11232 b"v3" => Error::UnexpectedEnd,
11233 b"v" => Error::UnexpectedEnd,
11234 b"" => Error::UnexpectedEnd,
11235 b"q" => Error::UnexpectedText,
11236 b"c" => Error::UnexpectedText,
11237 b"l" => Error::UnexpectedText,
11238 b"zzz" => Error::UnexpectedText,
11239 }
11240 });
11241 }
11242
11243 #[test]
parse_simple_operator_name()11244 fn parse_simple_operator_name() {
11245 assert_parse!(SimpleOperatorName {
11246 Ok => {
11247 b"qu" => {
11248 SimpleOperatorName::Question,
11249 b""
11250 }
11251 b"quokka" => {
11252 SimpleOperatorName::Question,
11253 b"okka"
11254 }
11255 }
11256 Err => {
11257 b"bu-buuuu" => Error::UnexpectedText,
11258 b"q" => Error::UnexpectedEnd,
11259 b"" => Error::UnexpectedEnd,
11260 }
11261 });
11262 }
11263 }
11264