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