llvm.org GIT mirror llvm / 42e40ea
Add a Microsoft Demangler. This adds initial support for a demangling library (LLVMDemangle) and tool (llvm-undname) for demangling Microsoft names. This doesn't cover 100% of cases and there are some known limitations which I intend to address in followup patches, at least until such time that we have (near) 100% test coverage matching up with all of the test cases in clang/test/CodeGenCXX/mangle-ms-*. Differential Revision: https://reviews.llvm.org/D49552 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@337584 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 1 year, 1 month ago
10 changed file(s) with 2259 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
1515 /// The mangled_name is demangled into buf and returned. If the buffer is not
1616 /// large enough, realloc is used to expand it.
1717 ///
18 /// The *status will be set to a value from the enumeration
18 /// The *status will be set to a value from the following enumeration
1919 enum : int {
2020 demangle_unknown_error = -4,
2121 demangle_invalid_args = -3,
2626
2727 char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n,
2828 int *status);
29 char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n,
30 int *status);
2931
3032 /// "Partial" demangler. This supports demangling a string into an AST
3133 /// (typically an intermediate stage in itaniumDemangle) and querying certain
0 add_llvm_library(LLVMDemangle
11 ItaniumDemangle.cpp
2
2 MicrosoftDemangle.cpp
3
34 ADDITIONAL_HEADER_DIRS
45 "${LLVM_MAIN_INCLUDE_DIR}/llvm/Demangle"
56 )
0 //===- MicrosoftDemangle.cpp ----------------------------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is dual licensed under the MIT and the University of Illinois Open
5 // Source Licenses. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a demangler for MSVC-style mangled symbols.
10 //
11 // This file has no dependencies on the rest of LLVM so that it can be
12 // easily reused in other programs such as libcxxabi.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "llvm/Demangle/Demangle.h"
17
18 #include "Compiler.h"
19 #include "StringView.h"
20 #include "Utility.h"
21
22 #include
23
24 // This memory allocator is extremely fast, but it doesn't call dtors
25 // for allocated objects. That means you can't use STL containers
26 // (such as std::vector) with this allocator. But it pays off --
27 // the demangler is 3x faster with this allocator compared to one with
28 // STL containers.
29 namespace {
30 class ArenaAllocator {
31 struct AllocatorNode {
32 uint8_t *Buf = nullptr;
33 size_t Used = 0;
34 AllocatorNode *Next = nullptr;
35 };
36
37 public:
38 ArenaAllocator() : Head(new AllocatorNode) { Head->Buf = new uint8_t[Unit]; }
39
40 ~ArenaAllocator() {
41 while (Head) {
42 assert(Head->Buf);
43 delete[] Head->Buf;
44 Head = Head->Next;
45 }
46 }
47
48 void *alloc(size_t Size) {
49 assert(Size < Unit);
50 assert(Head && Head->Buf);
51
52 uint8_t *P = Head->Buf + Head->Used;
53 Head->Used += Size;
54 if (Head->Used < Unit)
55 return P;
56
57 AllocatorNode *NewHead = new AllocatorNode;
58 NewHead->Buf = new uint8_t[ArenaAllocator::Unit];
59 NewHead->Next = Head;
60 Head = NewHead;
61 NewHead->Used = Size;
62 return NewHead->Buf;
63 }
64
65 private:
66 static constexpr size_t Unit = 4096;
67
68 AllocatorNode *Head = nullptr;
69 };
70 } // namespace
71
72 static bool startsWithDigit(StringView S) {
73 return !S.empty() && std::isdigit(S.front());
74 }
75
76 // Writes a space if the last token does not end with a punctuation.
77 static void outputSpaceIfNecessary(OutputStream &OS) {
78 if (OS.empty())
79 return;
80
81 char C = OS.back();
82 if (isalnum(C) || C == '>')
83 OS << " ";
84 }
85
86 void *operator new(size_t Size, ArenaAllocator &A) { return A.alloc(Size); }
87
88 // Storage classes
89 enum Qualifiers : uint8_t {
90 Q_None = 0,
91 Q_Const = 1 << 0,
92 Q_Volatile = 1 << 1,
93 Q_Far = 1 << 2,
94 Q_Huge = 1 << 3,
95 Q_Unaligned = 1 << 4,
96 Q_Restrict = 1 << 5,
97 Q_Pointer64 = 1 << 6
98 };
99
100 enum class StorageClass : uint8_t {
101 None,
102 PrivateStatic,
103 ProtectedStatic,
104 PublicStatic,
105 Global,
106 FunctionLocalStatic
107 };
108
109 enum class QualifierMangleMode { Drop, Mangle, Result };
110 enum class QualifierMangleLocation { Member, NonMember, Detect };
111
112 // Calling conventions
113 enum class CallingConv : uint8_t {
114 None,
115 Cdecl,
116 Pascal,
117 Thiscall,
118 Stdcall,
119 Fastcall,
120 Clrcall,
121 Eabi,
122 Vectorcall,
123 Regcall,
124 };
125
126 enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef };
127
128 // Types
129 enum class PrimTy : uint8_t {
130 Unknown,
131 None,
132 Function,
133 Ptr,
134 Ref,
135 Array,
136
137 Struct,
138 Union,
139 Class,
140 Enum,
141
142 Void,
143 Bool,
144 Char,
145 Schar,
146 Uchar,
147 Short,
148 Ushort,
149 Int,
150 Uint,
151 Long,
152 Ulong,
153 Int64,
154 Uint64,
155 Wchar,
156 Float,
157 Double,
158 Ldouble,
159 };
160
161 // Function classes
162 enum FuncClass : uint8_t {
163 Public = 1 << 0,
164 Protected = 1 << 1,
165 Private = 1 << 2,
166 Global = 1 << 3,
167 Static = 1 << 4,
168 Virtual = 1 << 5,
169 FFar = 1 << 6,
170 };
171
172 namespace {
173
174 struct Type;
175
176 // Represents a list of parameters (template params or function arguments.
177 // It's represented as a linked list.
178 struct ParamList {
179 Type *Current = nullptr;
180
181 ParamList *Next = nullptr;
182 };
183
184 // The type class. Mangled symbols are first parsed and converted to
185 // this type and then converted to string.
186 struct Type {
187 virtual ~Type() {}
188
189 virtual Type *clone(ArenaAllocator &Arena) const;
190
191 // Write the "first half" of a given type. This is a static functions to
192 // give the code a chance to do processing that is common to a subset of
193 // subclasses
194 static void outputPre(OutputStream &OS, Type &Ty);
195
196 // Write the "second half" of a given type. This is a static functions to
197 // give the code a chance to do processing that is common to a subset of
198 // subclasses
199 static void outputPost(OutputStream &OS, Type &Ty);
200
201 virtual void outputPre(OutputStream &OS);
202 virtual void outputPost(OutputStream &OS);
203
204 // Primitive type such as Int.
205 PrimTy Prim = PrimTy::Unknown;
206
207 Qualifiers Quals = Q_None;
208 StorageClass Storage = StorageClass::None; // storage class
209 };
210
211 // Represents an identifier which may be a template.
212 struct Name {
213 // Name read from an MangledName string.
214 StringView Str;
215
216 // Overloaded operators are represented as special BackReferences in mangled
217 // symbols. If this is an operator name, "op" has an operator name (e.g.
218 // ">>"). Otherwise, empty.
219 StringView Operator;
220
221 // Template parameters. Null if not a template.
222 ParamList TemplateParams;
223
224 // Nested BackReferences (e.g. "A::B::C") are represented as a linked list.
225 Name *Next = nullptr;
226 };
227
228 struct PointerType : public Type {
229 Type *clone(ArenaAllocator &Arena) const override;
230 void outputPre(OutputStream &OS);
231 void outputPost(OutputStream &OS) override;
232
233 bool isMemberPointer() const { return false; }
234
235 // Represents a type X in "a pointer to X", "a reference to X",
236 // "an array of X", or "a function returning X".
237 Type *Pointee = nullptr;
238 };
239
240 struct FunctionType : public Type {
241 Type *clone(ArenaAllocator &Arena) const override;
242 void outputPre(OutputStream &OS);
243 void outputPost(OutputStream &OS);
244
245 Type *ReturnType = nullptr;
246 // If this is a reference, the type of reference.
247 ReferenceKind RefKind;
248
249 CallingConv CallConvention;
250 FuncClass FunctionClass;
251
252 ParamList Params;
253 };
254
255 struct UdtType : public Type {
256 Type *clone(ArenaAllocator &Arena) const override;
257 void outputPre(OutputStream &OS) override;
258
259 Name *UdtName = nullptr;
260 };
261
262 struct ArrayType : public Type {
263 Type *clone(ArenaAllocator &Arena) const override;
264 void outputPre(OutputStream &OS) override;
265 void outputPost(OutputStream &OS) override;
266
267 // Either NextDimension or ElementType will be valid.
268 ArrayType *NextDimension = nullptr;
269 uint32_t ArrayDimension = 0;
270
271 Type *ElementType = nullptr;
272 };
273
274 } // namespace
275
276 static void outputCallingConvention(OutputStream &OS, CallingConv CC) {
277 outputSpaceIfNecessary(OS);
278
279 switch (CC) {
280 case CallingConv::Cdecl:
281 OS << "__cdecl";
282 break;
283 case CallingConv::Fastcall:
284 OS << "__fastcall";
285 break;
286 case CallingConv::Pascal:
287 OS << "__pascal";
288 break;
289 case CallingConv::Regcall:
290 OS << "__regcall";
291 break;
292 case CallingConv::Stdcall:
293 OS << "__stdcall";
294 break;
295 case CallingConv::Thiscall:
296 OS << "__thiscall";
297 break;
298 case CallingConv::Eabi:
299 OS << "__eabi";
300 break;
301 case CallingConv::Vectorcall:
302 OS << "__vectorcall";
303 break;
304 case CallingConv::Clrcall:
305 OS << "__clrcall";
306 break;
307 default:
308 break;
309 }
310 }
311
312 // Write a function or template parameter list.
313 static void outputParameterList(OutputStream &OS, const ParamList &Params) {
314 const ParamList *Head = &Params;
315 while (Head) {
316 Type::outputPre(OS, *Head->Current);
317 Type::outputPost(OS, *Head->Current);
318
319 Head = Head->Next;
320
321 if (Head)
322 OS << ", ";
323 }
324 }
325
326 static void outputTemplateParams(OutputStream &OS, const Name &TheName) {
327 if (!TheName.TemplateParams.Current)
328 return;
329
330 OS << "<";
331 outputParameterList(OS, TheName.TemplateParams);
332 OS << ">";
333 }
334
335 static void outputName(OutputStream &OS, const Name *TheName) {
336 if (!TheName)
337 return;
338
339 outputSpaceIfNecessary(OS);
340
341 // Print out namespaces or outer class BackReferences.
342 for (; TheName->Next; TheName = TheName->Next) {
343 OS << TheName->Str;
344 outputTemplateParams(OS, *TheName);
345 OS << "::";
346 }
347
348 // Print out a regular name.
349 if (TheName->Operator.empty()) {
350 OS << TheName->Str;
351 outputTemplateParams(OS, *TheName);
352 return;
353 }
354
355 // Print out ctor or dtor.
356 if (TheName->Operator == "ctor" || TheName->Operator == "dtor") {
357 OS << TheName->Str;
358 outputTemplateParams(OS, *TheName);
359 OS << "::";
360 if (TheName->Operator == "dtor")
361 OS << "~";
362 OS << TheName->Str;
363 outputTemplateParams(OS, *TheName);
364 return;
365 }
366
367 // Print out an overloaded operator.
368 if (!TheName->Str.empty())
369 OS << TheName->Str << "::";
370 OS << "operator" << TheName->Operator;
371 }
372
373 namespace {
374
375 Type *Type::clone(ArenaAllocator &Arena) const {
376 return new (Arena) Type(*this);
377 }
378
379 // Write the "first half" of a given type.
380 void Type::outputPre(OutputStream &OS, Type &Ty) {
381 // Function types require custom handling of const and static so we
382 // handle them separately. All other types use the same decoration
383 // for these modifiers, so handle them here in common code.
384 if (Ty.Prim == PrimTy::Function) {
385 Ty.outputPre(OS);
386 return;
387 }
388
389 switch (Ty.Storage) {
390 case StorageClass::PrivateStatic:
391 case StorageClass::PublicStatic:
392 case StorageClass::ProtectedStatic:
393 OS << "static ";
394 default:
395 break;
396 }
397 Ty.outputPre(OS);
398
399 if (Ty.Quals & Q_Const) {
400 outputSpaceIfNecessary(OS);
401 OS << "const";
402 }
403
404 if (Ty.Quals & Q_Volatile) {
405 outputSpaceIfNecessary(OS);
406 OS << "volatile";
407 }
408 }
409
410 // Write the "second half" of a given type.
411 void Type::outputPost(OutputStream &OS, Type &Ty) { Ty.outputPost(OS); }
412
413 void Type::outputPre(OutputStream &OS) {
414 switch (Prim) {
415 case PrimTy::Void:
416 OS << "void";
417 break;
418 case PrimTy::Bool:
419 OS << "bool";
420 break;
421 case PrimTy::Char:
422 OS << "char";
423 break;
424 case PrimTy::Schar:
425 OS << "signed char";
426 break;
427 case PrimTy::Uchar:
428 OS << "unsigned char";
429 break;
430 case PrimTy::Short:
431 OS << "short";
432 break;
433 case PrimTy::Ushort:
434 OS << "unsigned short";
435 break;
436 case PrimTy::Int:
437 OS << "int";
438 break;
439 case PrimTy::Uint:
440 OS << "unsigned int";
441 break;
442 case PrimTy::Long:
443 OS << "long";
444 break;
445 case PrimTy::Ulong:
446 OS << "unsigned long";
447 break;
448 case PrimTy::Int64:
449 OS << "__int64";
450 break;
451 case PrimTy::Uint64:
452 OS << "unsigned __int64";
453 break;
454 case PrimTy::Wchar:
455 OS << "wchar_t";
456 break;
457 case PrimTy::Float:
458 OS << "float";
459 break;
460 case PrimTy::Double:
461 OS << "double";
462 break;
463 case PrimTy::Ldouble:
464 OS << "long double";
465 break;
466 default:
467 assert(false && "Invalid primitive type!");
468 }
469 }
470 void Type::outputPost(OutputStream &OS) {}
471
472 Type *PointerType::clone(ArenaAllocator &Arena) const {
473 return new (Arena) PointerType(*this);
474 }
475
476 void PointerType::outputPre(OutputStream &OS) {
477 Type::outputPre(OS, *Pointee);
478
479 outputSpaceIfNecessary(OS);
480
481 if (Quals & Q_Unaligned)
482 OS << "__unaligned ";
483
484 // "[]" and "()" (for function parameters) take precedence over "*",
485 // so "int *x(int)" means "x is a function returning int *". We need
486 // parentheses to supercede the default precedence. (e.g. we want to
487 // emit something like "int (*x)(int)".)
488 if (Pointee->Prim == PrimTy::Function || Pointee->Prim == PrimTy::Array)
489 OS << "(";
490
491 if (Prim == PrimTy::Ptr)
492 OS << "*";
493 else
494 OS << "&";
495
496 // if (Ty.Quals & Q_Pointer64)
497 // OS << " __ptr64";
498 if (Quals & Q_Restrict)
499 OS << " __restrict";
500 }
501
502 void PointerType::outputPost(OutputStream &OS) {
503 if (Pointee->Prim == PrimTy::Function || Pointee->Prim == PrimTy::Array)
504 OS << ")";
505
506 Type::outputPost(OS, *Pointee);
507 }
508
509 Type *FunctionType::clone(ArenaAllocator &Arena) const {
510 return new (Arena) FunctionType(*this);
511 }
512
513 void FunctionType::outputPre(OutputStream &OS) {
514 if (!(FunctionClass & Global)) {
515 if (FunctionClass & Static)
516 OS << "static ";
517 }
518
519 if (ReturnType)
520 Type::outputPre(OS, *ReturnType);
521
522 outputCallingConvention(OS, CallConvention);
523 }
524
525 void FunctionType::outputPost(OutputStream &OS) {
526 OS << "(";
527 outputParameterList(OS, Params);
528 OS << ")";
529 if (Quals & Q_Const)
530 OS << " const";
531 if (Quals & Q_Volatile)
532 OS << " volatile";
533 return;
534 }
535
536 Type *UdtType::clone(ArenaAllocator &Arena) const {
537 return new (Arena) UdtType(*this);
538 }
539
540 void UdtType::outputPre(OutputStream &OS) {
541 switch (Prim) {
542 case PrimTy::Class:
543 OS << "class ";
544 break;
545 case PrimTy::Struct:
546 OS << "struct ";
547 break;
548 case PrimTy::Union:
549 OS << "union ";
550 break;
551 case PrimTy::Enum:
552 OS << "enum ";
553 break;
554 default:
555 assert(false && "Not a udt type!");
556 }
557
558 outputName(OS, UdtName);
559 }
560
561 Type *ArrayType::clone(ArenaAllocator &Arena) const {
562 return new (Arena) ArrayType(*this);
563 }
564
565 void ArrayType::outputPre(OutputStream &OS) {
566 Type::outputPre(OS, *ElementType);
567 }
568
569 void ArrayType::outputPost(OutputStream &OS) {
570 if (ArrayDimension > 0)
571 OS << "[" << ArrayDimension << "]";
572 if (NextDimension)
573 Type::outputPost(OS, *NextDimension);
574 else if (ElementType)
575 Type::outputPost(OS, *ElementType);
576 }
577
578 } // namespace
579
580 namespace {
581
582 // Demangler class takes the main role in demangling symbols.
583 // It has a set of functions to parse mangled symbols into Type instances.
584 // It also has a set of functions to cnovert Type instances to strings.
585 class Demangler {
586 public:
587 Demangler(OutputStream &OS, StringView s) : OS(OS), MangledName(s) {}
588
589 // You are supposed to call parse() first and then check if error is true. If
590 // it is false, call output() to write the formatted name to the given stream.
591 void parse();
592 void output();
593
594 // True if an error occurred.
595 bool Error = false;
596
597 private:
598 Type *demangleVariableEncoding();
599 Type *demangleFunctionEncoding();
600
601 Qualifiers demanglePointerExtQualifiers();
602
603 // Parser functions. This is a recursive-descent parser.
604 Type *demangleType(QualifierMangleMode QMM);
605 Type *demangleBasicType();
606 UdtType *demangleClassType();
607 PointerType *demanglePointerType();
608
609 ArrayType *demangleArrayType();
610
611 ParamList demangleParameterList();
612
613 int demangleNumber();
614 void demangleNamePiece(Name &Node, bool IsHead);
615
616 StringView demangleString(bool memorize);
617 void memorizeString(StringView s);
618 Name *demangleName();
619 void demangleOperator(Name *);
620 StringView demangleOperatorName();
621 int demangleFunctionClass();
622 CallingConv demangleCallingConvention();
623 StorageClass demangleVariableStorageClass();
624 ReferenceKind demangleReferenceKind();
625
626 Qualifiers demangleFunctionQualifiers();
627 Qualifiers demangleVariablQ_ifiers();
628 Qualifiers demangleReturnTypQ_ifiers();
629
630 Qualifiers demangleQualifiers(
631 QualifierMangleLocation Location = QualifierMangleLocation::Detect);
632
633 // Mangled symbol. demangle* functions shorten this string
634 // as they parse it.
635 StringView MangledName;
636
637 // A parsed mangled symbol.
638 Type *SymbolType;
639
640 // The main symbol name. (e.g. "ns::foo" in "int ns::foo()".)
641 Name *SymbolName = nullptr;
642
643 // Memory allocator.
644 ArenaAllocator Arena;
645
646 // The first 10 BackReferences in a mangled name can be back-referenced by
647 // special name @[0-9]. This is a storage for the first 10 BackReferences.
648 StringView BackReferences[10];
649 size_t BackRefCount = 0;
650
651 // The result is written to this stream.
652 OutputStream OS;
653 };
654 } // namespace
655
656 // Parser entry point.
657 void Demangler::parse() {
658 // MSVC-style mangled symbols must start with '?'.
659 if (!MangledName.consumeFront("?")) {
660 SymbolName = new (Arena) Name;
661 SymbolName->Str = MangledName;
662 SymbolType = new (Arena) Type;
663 SymbolType->Prim = PrimTy::Unknown;
664 }
665
666 // What follows is a main symbol name. This may include
667 // namespaces or class BackReferences.
668 SymbolName = demangleName();
669
670 // Read a variable.
671 if (startsWithDigit(MangledName)) {
672 SymbolType = demangleVariableEncoding();
673 return;
674 }
675
676 // Read a function.
677 SymbolType = demangleFunctionEncoding();
678 }
679
680 // ::=
681 // ::= 0 # private static member
682 // ::= 1 # protected static member
683 // ::= 2 # public static member
684 // ::= 3 # global
685 // ::= 4 # static local
686
687 Type *Demangler::demangleVariableEncoding() {
688 StorageClass SC = demangleVariableStorageClass();
689
690 Type *Ty = demangleType(QualifierMangleMode::Drop);
691
692 Ty->Storage = SC;
693
694 // ::=
695 // ::= # pointers, references
696 switch (Ty->Prim) {
697 case PrimTy::Ptr:
698 case PrimTy::Ref: {
699 Qualifiers ExtraChildQuals = Q_None;
700 Ty->Quals = Qualifiers(Ty->Quals | demanglePointerExtQualifiers());
701
702 PointerType *PTy = static_cast(Ty);
703 QualifierMangleLocation Location = PTy->isMemberPointer()
704 ? QualifierMangleLocation::Member
705 : QualifierMangleLocation::NonMember;
706
707 ExtraChildQuals = demangleQualifiers(Location);
708
709 if (PTy->isMemberPointer()) {
710 Name *BackRefName = demangleName();
711 (void)BackRefName;
712 }
713
714 PTy->Pointee->Quals = Qualifiers(PTy->Pointee->Quals | ExtraChildQuals);
715 break;
716 }
717 default:
718 Ty->Quals = demangleQualifiers();
719 break;
720 }
721
722 return Ty;
723 }
724
725 // Sometimes numbers are encoded in mangled symbols. For example,
726 // "int (*x)[20]" is a valid C type (x is a pointer to an array of
727 // length 20), so we need some way to embed numbers as part of symbols.
728 // This function parses it.
729 //
730 // ::= [?]
731 //
732 // ::= # when 1 <= Number <= 10
733 // ::= + @ # when Numbrer == 0 or >= 10
734 //
735 // ::= [A-P] # A = 0, B = 1, ...
736 int Demangler::demangleNumber() {
737 bool neg = MangledName.consumeFront("?");
738
739 if (startsWithDigit(MangledName)) {
740 int32_t Ret = MangledName[0] - '0' + 1;
741 MangledName = MangledName.dropFront(1);
742 return neg ? -Ret : Ret;
743 }
744
745 int Ret = 0;
746 for (size_t i = 0; i < MangledName.size(); ++i) {
747 char C = MangledName[i];
748 if (C == '@') {
749 MangledName = MangledName.dropFront(i + 1);
750 return neg ? -Ret : Ret;
751 }
752 if ('A' <= C && C <= 'P') {
753 Ret = (Ret << 4) + (C - 'A');
754 continue;
755 }
756 break;
757 }
758
759 Error = true;
760 return 0;
761 }
762
763 // Read until the next '@'.
764 StringView Demangler::demangleString(bool Memorize) {
765 for (size_t i = 0; i < MangledName.size(); ++i) {
766 if (MangledName[i] != '@')
767 continue;
768 StringView ret = MangledName.substr(0, i);
769 MangledName = MangledName.dropFront(i + 1);
770
771 if (Memorize)
772 memorizeString(ret);
773 return ret;
774 }
775
776 Error = true;
777 return "";
778 }
779
780 // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9.
781 // Memorize it.
782 void Demangler::memorizeString(StringView S) {
783 if (BackRefCount >= sizeof(BackReferences) / sizeof(*BackReferences))
784 return;
785 for (size_t i = 0; i < BackRefCount; ++i)
786 if (S == BackReferences[i])
787 return;
788 BackReferences[BackRefCount++] = S;
789 }
790
791 void Demangler::demangleNamePiece(Name &Node, bool IsHead) {
792 if (startsWithDigit(MangledName)) {
793 size_t I = MangledName[0] - '0';
794 if (I >= BackRefCount) {
795 Error = true;
796 return;
797 }
798 MangledName = MangledName.dropFront();
799 Node.Str = BackReferences[I];
800 } else if (MangledName.consumeFront("?$")) {
801 // Class template.
802 Node.Str = demangleString(false);
803 Node.TemplateParams = demangleParameterList();
804 if (!MangledName.consumeFront('@')) {
805 Error = true;
806 return;
807 }
808 } else if (!IsHead && MangledName.consumeFront("?A")) {
809 // Anonymous namespace starts with ?A. So does overloaded operator[],
810 // but the distinguishing factor is that namespace themselves are not
811 // mangled, only the variables and functions inside of them are. So
812 // an anonymous namespace will never occur as the first item in the
813 // name.
814 Node.Str = "`anonymous namespace'";
815 if (!MangledName.consumeFront('@')) {
816 Error = true;
817 return;
818 }
819 } else if (MangledName.consumeFront("?")) {
820 // Overloaded operator.
821 demangleOperator(&Node);
822 } else {
823 // Non-template functions or classes.
824 Node.Str = demangleString(true);
825 }
826 }
827
828 // Parses a name in the form of A@B@C@@ which represents C::B::A.
829 Name *Demangler::demangleName() {
830 Name *Head = nullptr;
831
832 while (!MangledName.consumeFront("@")) {
833 Name *Elem = new (Arena) Name;
834
835 assert(!Error);
836 demangleNamePiece(*Elem, Head == nullptr);
837 if (Error)
838 return nullptr;
839
840 Elem->Next = Head;
841 Head = Elem;
842 }
843
844 return Head;
845 }
846
847 void Demangler::demangleOperator(Name *OpName) {
848 OpName->Operator = demangleOperatorName();
849 if (!Error && !MangledName.empty() && MangledName.front() != '@')
850 demangleNamePiece(*OpName, false);
851 }
852
853 StringView Demangler::demangleOperatorName() {
854 SwapAndRestore RestoreOnError(MangledName, MangledName);
855 RestoreOnError.shouldRestore(false);
856
857 switch (MangledName.popFront()) {
858 case '0':
859 return "ctor";
860 case '1':
861 return "dtor";
862 case '2':
863 return " new";
864 case '3':
865 return " delete";
866 case '4':
867 return "=";
868 case '5':
869 return ">>";
870 case '6':
871 return "<<";
872 case '7':
873 return "!";
874 case '8':
875 return "==";
876 case '9':
877 return "!=";
878 case 'A':
879 return "[]";
880 case 'C':
881 return "->";
882 case 'D':
883 return "*";
884 case 'E':
885 return "++";
886 case 'F':
887 return "--";
888 case 'G':
889 return "-";
890 case 'H':
891 return "+";
892 case 'I':
893 return "&";
894 case 'J':
895 return "->*";
896 case 'K':
897 return "/";
898 case 'L':
899 return "%";
900 case 'M':
901 return "<";
902 case 'N':
903 return "<=";
904 case 'O':
905 return ">";
906 case 'P':
907 return ">=";
908 case 'Q':
909 return ",";
910 case 'R':
911 return "()";
912 case 'S':
913 return "~";
914 case 'T':
915 return "^";
916 case 'U':
917 return "|";
918 case 'V':
919 return "&&";
920 case 'W':
921 return "||";
922 case 'X':
923 return "*=";
924 case 'Y':
925 return "+=";
926 case 'Z':
927 return "-=";
928 case '_': {
929 if (MangledName.empty())
930 break;
931
932 switch (MangledName.popFront()) {
933 case '0':
934 return "/=";
935 case '1':
936 return "%=";
937 case '2':
938 return ">>=";
939 case '3':
940 return "<<=";
941 case '4':
942 return "&=";
943 case '5':
944 return "|=";
945 case '6':
946 return "^=";
947 case 'U':
948 return " new[]";
949 case 'V':
950 return " delete[]";
951 case '_':
952 if (MangledName.consumeFront("L"))
953 return " co_await";
954 }
955 }
956 }
957
958 Error = true;
959 RestoreOnError.shouldRestore(true);
960 return "";
961 }
962
963 int Demangler::demangleFunctionClass() {
964 SwapAndRestore RestoreOnError(MangledName, MangledName);
965 RestoreOnError.shouldRestore(false);
966
967 switch (MangledName.popFront()) {
968 case 'A':
969 return Private;
970 case 'B':
971 return Private | FFar;
972 case 'C':
973 return Private | Static;
974 case 'D':
975 return Private | Static;
976 case 'E':
977 return Private | Virtual;
978 case 'F':
979 return Private | Virtual;
980 case 'I':
981 return Protected;
982 case 'J':
983 return Protected | FFar;
984 case 'K':
985 return Protected | Static;
986 case 'L':
987 return Protected | Static | FFar;
988 case 'M':
989 return Protected | Virtual;
990 case 'N':
991 return Protected | Virtual | FFar;
992 case 'Q':
993 return Public;
994 case 'R':
995 return Public | FFar;
996 case 'S':
997 return Public | Static;
998 case 'T':
999 return Public | Static | FFar;
1000 case 'U':
1001 return Public | Virtual;
1002 case 'V':
1003 return Public | Virtual | FFar;
1004 case 'Y':
1005 return Global;
1006 case 'Z':
1007 return Global | FFar;
1008 }
1009
1010 Error = true;
1011 RestoreOnError.shouldRestore(true);
1012 return 0;
1013 }
1014
1015 Qualifiers Demangler::demangleFunctionQualifiers() {
1016 SwapAndRestore RestoreOnError(MangledName, MangledName);
1017 RestoreOnError.shouldRestore(false);
1018
1019 switch (MangledName.popFront()) {
1020 case 'A':
1021 return Q_None;
1022 case 'B':
1023 return Q_Const;
1024 case 'C':
1025 return Q_Volatile;
1026 case 'D':
1027 return Qualifiers(Q_Const | Q_Volatile);
1028 }
1029
1030 Error = true;
1031 RestoreOnError.shouldRestore(true);
1032 return Q_None;
1033 }
1034
1035 CallingConv Demangler::demangleCallingConvention() {
1036 switch (MangledName.popFront()) {
1037 case 'A':
1038 case 'B':
1039 return CallingConv::Cdecl;
1040 case 'C':
1041 case 'D':
1042 return CallingConv::Pascal;
1043 case 'E':
1044 case 'F':
1045 return CallingConv::Thiscall;
1046 case 'G':
1047 case 'H':
1048 return CallingConv::Stdcall;
1049 case 'I':
1050 case 'J':
1051 return CallingConv::Fastcall;
1052 case 'M':
1053 case 'N':
1054 return CallingConv::Clrcall;
1055 case 'O':
1056 case 'P':
1057 return CallingConv::Eabi;
1058 case 'Q':
1059 return CallingConv::Vectorcall;
1060 }
1061
1062 return CallingConv::None;
1063 };
1064
1065 StorageClass Demangler::demangleVariableStorageClass() {
1066 assert(std::isdigit(MangledName.front()));
1067
1068 switch (MangledName.popFront()) {
1069 case '0':
1070 return StorageClass::PrivateStatic;
1071 case '1':
1072 return StorageClass::ProtectedStatic;
1073 case '2':
1074 return StorageClass::PublicStatic;
1075 case '3':
1076 return StorageClass::Global;
1077 case '4':
1078 return StorageClass::FunctionLocalStatic;
1079 }
1080 Error = true;
1081 return StorageClass::None;
1082 }
1083
1084 Qualifiers Demangler::demangleVariablQ_ifiers() {
1085 SwapAndRestore RestoreOnError(MangledName, MangledName);
1086 RestoreOnError.shouldRestore(false);
1087
1088 switch (MangledName.popFront()) {
1089 case 'A':
1090 return Q_None;
1091 case 'B':
1092 return Q_Const;
1093 case 'C':
1094 return Q_Volatile;
1095 case 'D':
1096 return Qualifiers(Q_Const | Q_Volatile);
1097 case 'E':
1098 return Q_Far;
1099 case 'F':
1100 return Qualifiers(Q_Const | Q_Far);
1101 case 'G':
1102 return Qualifiers(Q_Volatile | Q_Far);
1103 case 'H':
1104 return Qualifiers(Q_Const | Q_Volatile | Q_Far);
1105 }
1106
1107 Error = true;
1108 RestoreOnError.shouldRestore(true);
1109 return Q_None;
1110 }
1111
1112 Qualifiers Demangler::demangleReturnTypQ_ifiers() {
1113 if (!MangledName.consumeFront("?"))
1114 return Q_None;
1115
1116 SwapAndRestore RestoreOnError(MangledName, MangledName);
1117 RestoreOnError.shouldRestore(false);
1118
1119 switch (MangledName.popFront()) {
1120 case 'A':
1121 return Q_None;
1122 case 'B':
1123 return Q_Const;
1124 case 'C':
1125 return Q_Volatile;
1126 case 'D':
1127 return Qualifiers(Q_Const | Q_Volatile);
1128 }
1129
1130 Error = true;
1131 RestoreOnError.shouldRestore(true);
1132 return Q_None;
1133 }
1134
1135 Qualifiers Demangler::demangleQualifiers(QualifierMangleLocation Location) {
1136 if (Location == QualifierMangleLocation::Detect) {
1137 switch (MangledName.front()) {
1138 case 'Q':
1139 case 'R':
1140 case 'S':
1141 case 'T':
1142 Location = QualifierMangleLocation::Member;
1143 break;
1144 case 'A':
1145 case 'B':
1146 case 'C':
1147 case 'D':
1148 Location = QualifierMangleLocation::NonMember;
1149 break;
1150 default:
1151 Error = true;
1152 return Q_None;
1153 }
1154 }
1155
1156 if (Location == QualifierMangleLocation::Member) {
1157 switch (MangledName.popFront()) {
1158 // Member qualifiers
1159 case 'Q':
1160 return Q_None;
1161 case 'R':
1162 return Q_Const;
1163 case 'S':
1164 return Q_Volatile;
1165 case 'T':
1166 return Qualifiers(Q_Const | Q_Volatile);
1167 }
1168 } else {
1169 switch (MangledName.popFront()) {
1170 // Non-Member qualifiers
1171 case 'A':
1172 return Q_None;
1173 case 'B':
1174 return Q_Const;
1175 case 'C':
1176 return Q_Volatile;
1177 case 'D':
1178 return Qualifiers(Q_Const | Q_Volatile);
1179 }
1180 }
1181 Error = true;
1182 return Q_None;
1183 }
1184
1185 // ::=
1186 // ::= # pointers, references
1187 Type *Demangler::demangleType(QualifierMangleMode QMM) {
1188 Qualifiers Quals = Q_None;
1189 if (QMM == QualifierMangleMode::Mangle)
1190 Quals = Qualifiers(Quals | demangleQualifiers());
1191 else if (QMM == QualifierMangleMode::Result) {
1192 if (MangledName.consumeFront('?'))
1193 Quals = Qualifiers(Quals | demangleQualifiers());
1194 }
1195
1196 Type *Ty = nullptr;
1197 switch (MangledName.front()) {
1198 case 'T': // union
1199 case 'U': // struct
1200 case 'V': // class
1201 case 'W': // enum
1202 Ty = demangleClassType();
1203 break;
1204 case 'A': // foo &
1205 case 'P': // foo *
1206 case 'Q': // foo *const
1207 case 'R': // foo *volatile
1208 case 'S': // foo *const volatile
1209 Ty = demanglePointerType();
1210 break;
1211 case 'Y':
1212 Ty = demangleArrayType();
1213 break;
1214 default:
1215 Ty = demangleBasicType();
1216 break;
1217 }
1218 Ty->Quals = Qualifiers(Ty->Quals | Quals);
1219 return Ty;
1220 }
1221
1222 static bool functionHasThisPtr(const FunctionType &Ty) {
1223 assert(Ty.Prim == PrimTy::Function);
1224 if (Ty.FunctionClass & Global)
1225 return false;
1226 if (Ty.FunctionClass & Static)
1227 return false;
1228 return true;
1229 }
1230
1231 ReferenceKind Demangler::demangleReferenceKind() {
1232 if (MangledName.consumeFront('G'))
1233 return ReferenceKind::LValueRef;
1234 else if (MangledName.consumeFront('H'))
1235 return ReferenceKind::RValueRef;
1236 return ReferenceKind::None;
1237 }
1238
1239 Type *Demangler::demangleFunctionEncoding() {
1240 FunctionType *FTy = new (Arena) FunctionType;
1241
1242 FTy->Prim = PrimTy::Function;
1243 FTy->FunctionClass = (FuncClass)demangleFunctionClass();
1244 if (functionHasThisPtr(*FTy)) {
1245 FTy->Quals = demanglePointerExtQualifiers();
1246 FTy->RefKind = demangleReferenceKind();
1247 FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers());
1248 }
1249
1250 // Fields that appear on both member and non-member functions.
1251 FTy->CallConvention = demangleCallingConvention();
1252
1253 // ::=
1254 // ::= @ # structors (they have no declared return type)
1255 bool IsStructor = MangledName.consumeFront('@');
1256 if (!IsStructor)
1257 FTy->ReturnType = demangleType(QualifierMangleMode::Result);
1258
1259 FTy->Params = demangleParameterList();
1260
1261 return FTy;
1262 }
1263
1264 // Reads a primitive type.
1265 Type *Demangler::demangleBasicType() {
1266 Type *Ty = new (Arena) Type;
1267
1268 switch (MangledName.popFront()) {
1269 case 'X':
1270 Ty->Prim = PrimTy::Void;
1271 break;
1272 case 'D':
1273 Ty->Prim = PrimTy::Char;
1274 break;
1275 case 'C':
1276 Ty->Prim = PrimTy::Schar;
1277 break;
1278 case 'E':
1279 Ty->Prim = PrimTy::Uchar;
1280 break;
1281 case 'F':
1282 Ty->Prim = PrimTy::Short;
1283 break;
1284 case 'G':
1285 Ty->Prim = PrimTy::Ushort;
1286 break;
1287 case 'H':
1288 Ty->Prim = PrimTy::Int;
1289 break;
1290 case 'I':
1291 Ty->Prim = PrimTy::Uint;
1292 break;
1293 case 'J':
1294 Ty->Prim = PrimTy::Long;
1295 break;
1296 case 'K':
1297 Ty->Prim = PrimTy::Ulong;
1298 break;
1299 case 'M':
1300 Ty->Prim = PrimTy::Float;
1301 break;
1302 case 'N':
1303 Ty->Prim = PrimTy::Double;
1304 break;
1305 case 'O':
1306 Ty->Prim = PrimTy::Ldouble;
1307 break;
1308 case '_': {
1309 switch (MangledName.popFront()) {
1310 case 'N':
1311 Ty->Prim = PrimTy::Bool;
1312 break;
1313 case 'J':
1314 Ty->Prim = PrimTy::Int64;
1315 break;
1316 case 'K':
1317 Ty->Prim = PrimTy::Uint64;
1318 break;
1319 case 'W':
1320 Ty->Prim = PrimTy::Wchar;
1321 break;
1322 }
1323 break;
1324 }
1325 }
1326 return Ty;
1327 }
1328
1329 UdtType *Demangler::demangleClassType() {
1330 UdtType *UTy = new (Arena) UdtType;
1331
1332 switch (MangledName.popFront()) {
1333 case 'T':
1334 UTy->Prim = PrimTy::Union;
1335 break;
1336 case 'U':
1337 UTy->Prim = PrimTy::Struct;
1338 break;
1339 case 'V':
1340 UTy->Prim = PrimTy::Class;
1341 break;
1342 case 'W':
1343 if (MangledName.popFront() != '4') {
1344 Error = true;
1345 return nullptr;
1346 }
1347 UTy->Prim = PrimTy::Enum;
1348 break;
1349 default:
1350 assert(false);
1351 }
1352
1353 UTy->UdtName = demangleName();
1354 return UTy;
1355 }
1356
1357 // ::= E?
1358 // # the E is required for 64-bit non-static pointers
1359 PointerType *Demangler::demanglePointerType() {
1360 PointerType *Pointer = new (Arena) PointerType;
1361
1362 Pointer->Quals = Q_None;
1363 switch (MangledName.popFront()) {
1364 case 'A':
1365 Pointer->Prim = PrimTy::Ref;
1366 break;
1367 case 'P':
1368 Pointer->Prim = PrimTy::Ptr;
1369 break;
1370 case 'Q':
1371 Pointer->Prim = PrimTy::Ptr;
1372 Pointer->Quals = Q_Const;
1373 break;
1374 case 'R':
1375 Pointer->Quals = Q_Volatile;
1376 Pointer->Prim = PrimTy::Ptr;
1377 break;
1378 case 'S':
1379 Pointer->Quals = Qualifiers(Q_Const | Q_Volatile);
1380 Pointer->Prim = PrimTy::Ptr;
1381 break;
1382 default:
1383 assert(false && "Ty is not a pointer type!");
1384 }
1385
1386 if (MangledName.consumeFront("6")) {
1387 FunctionType *FTy = new (Arena) FunctionType;
1388 FTy->Prim = PrimTy::Function;
1389 FTy->CallConvention = demangleCallingConvention();
1390
1391 FTy->ReturnType = demangleType(QualifierMangleMode::Drop);
1392 FTy->Params = demangleParameterList();
1393
1394 if (!MangledName.consumeFront("@Z"))
1395 MangledName.consumeFront("Z");
1396
1397 Pointer->Pointee = FTy;
1398 return Pointer;
1399 }
1400
1401 Qualifiers ExtQuals = demanglePointerExtQualifiers();
1402 Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
1403
1404 Pointer->Pointee = demangleType(QualifierMangleMode::Mangle);
1405 return Pointer;
1406 }
1407
1408 Qualifiers Demangler::demanglePointerExtQualifiers() {
1409 Qualifiers Quals = Q_None;
1410 if (MangledName.consumeFront('E'))
1411 Quals = Qualifiers(Quals | Q_Pointer64);
1412 if (MangledName.consumeFront('I'))
1413 Quals = Qualifiers(Quals | Q_Restrict);
1414 if (MangledName.consumeFront('F'))
1415 Quals = Qualifiers(Quals | Q_Unaligned);
1416
1417 return Quals;
1418 }
1419
1420 ArrayType *Demangler::demangleArrayType() {
1421 assert(MangledName.front() == 'Y');
1422 MangledName.popFront();
1423
1424 int Dimension = demangleNumber();
1425 if (Dimension <= 0) {
1426 Error = true;
1427 return nullptr;
1428 }
1429
1430 ArrayType *ATy = new (Arena) ArrayType;
1431 ArrayType *Dim = ATy;
1432 for (int I = 0; I < Dimension; ++I) {
1433 Dim->Prim = PrimTy::Array;
1434 Dim->ArrayDimension = demangleNumber();
1435 Dim->NextDimension = new (Arena) ArrayType;
1436 Dim = Dim->NextDimension;
1437 }
1438
1439 if (MangledName.consumeFront("$$C")) {
1440 if (MangledName.consumeFront("B"))
1441 ATy->Quals = Q_Const;
1442 else if (MangledName.consumeFront("C") || MangledName.consumeFront("D"))
1443 ATy->Quals = Qualifiers(Q_Const | Q_Volatile);
1444 else if (!MangledName.consumeFront("A"))
1445 Error = true;
1446 }
1447
1448 ATy->ElementType = demangleType(QualifierMangleMode::Drop);
1449 Dim->ElementType = ATy->ElementType;
1450 return ATy;
1451 }
1452
1453 // Reads a function or a template parameters.
1454 ParamList Demangler::demangleParameterList() {
1455 // Within the same parameter list, you can backreference the first 10 types.
1456 Type *BackRef[10];
1457 int Idx = 0;
1458
1459 ParamList *Head;
1460 ParamList **Current = &Head;
1461 while (!Error && !MangledName.startsWith('@') &&
1462 !MangledName.startsWith('Z')) {
1463 if (startsWithDigit(MangledName)) {
1464 int N = MangledName[0] - '0';
1465 if (N >= Idx) {
1466 Error = true;
1467 return {};
1468 }
1469 MangledName = MangledName.dropFront();
1470
1471 *Current = new (Arena) ParamList;
1472 (*Current)->Current = BackRef[N]->clone(Arena);
1473 Current = &(*Current)->Next;
1474 continue;
1475 }
1476
1477 size_t ArrayDimension = MangledName.size();
1478
1479 *Current = new (Arena) ParamList;
1480 (*Current)->Current = demangleType(QualifierMangleMode::Drop);
1481
1482 // Single-letter types are ignored for backreferences because
1483 // memorizing them doesn't save anything.
1484 if (Idx <= 9 && ArrayDimension - MangledName.size() > 1)
1485 BackRef[Idx++] = (*Current)->Current;
1486 Current = &(*Current)->Next;
1487 }
1488
1489 return *Head;
1490 }
1491
1492 void Demangler::output() {
1493 // Converts an AST to a string.
1494 //
1495 // Converting an AST representing a C++ type to a string is tricky due
1496 // to the bad grammar of the C++ declaration inherited from C. You have
1497 // to construct a string from inside to outside. For example, if a type
1498 // X is a pointer to a function returning int, the order you create a
1499 // string becomes something like this:
1500 //
1501 // (1) X is a pointer: *X
1502 // (2) (1) is a function returning int: int (*X)()
1503 //
1504 // So you cannot construct a result just by appending strings to a result.
1505 //
1506 // To deal with this, we split the function into two. outputPre() writes
1507 // the "first half" of type declaration, and outputPost() writes the
1508 // "second half". For example, outputPre() writes a return type for a
1509 // function and outputPost() writes an parameter list.
1510 Type::outputPre(OS, *SymbolType);
1511 outputName(OS, SymbolName);
1512 Type::outputPost(OS, *SymbolType);
1513
1514 // Null terminate the buffer.
1515 OS << '\0';
1516 }
1517
1518 char *llvm::microsoftDemangle(const char *MangledName, char *Buf, size_t *N,
1519 int *Status) {
1520 OutputStream OS = OutputStream::create(Buf, N, 1024);
1521
1522 Demangler D(OS, StringView(MangledName));
1523 D.parse();
1524
1525 if (D.Error)
1526 *Status = llvm::demangle_invalid_mangled_name;
1527 else
1528 *Status = llvm::demangle_success;
1529
1530 D.output();
1531 return OS.getBuffer();
1532 }
0 ; RUN: llvm-undname < %s | FileCheck %s
1
2 ; CHECK-NOT: Invalid mangled name
3
4 ?x@@3HA
5 ; CHECK: int x
6
7 ?x@@3PEAHEA
8 ; CHECK: int *x
9
10 ?x@@3PEAPEAHEA
11 ; CHECK: int **x
12
13 ?x@@3PEAY02HEA
14 ; CHECK: int (*x)[3]
15
16 ?x@@3PEAY124HEA
17 ; CHECK: int (*x)[3][5]
18
19 ?x@@3PEAY02$$CBHEA
20 ; CHECK: int const (*x)[3]
21
22 ?x@@3PEAEEA
23 ; CHECK: unsigned char *x
24
25 ?x@@3PEAY1NKM@5HEA
26 ; CHECK: int (*x)[3500][6]
27
28 ?x@@YAXMH@Z
29 ; CHECK: void __cdecl x(float, int)
30
31 ?x@@3P6AHMNH@ZEA
32 ; CHECK: int __cdecl (*x)(float, double, int)
33
34 ?x@@3P6AHP6AHM@ZN@ZEA
35 ; CHECK: int __cdecl (*x)(int __cdecl (*)(float), double)
36
37 ?x@@3P6AHP6AHM@Z0@ZEA
38 ; CHECK: int __cdecl (*x)(int __cdecl (*)(float), int __cdecl (*)(float))
39
40 ?x@ns@@3HA
41 ; CHECK: int ns::x
42
43 ; Microsoft's undname doesn't handle Q correctly or the multiple occurrences
44 ; of the const modifier. So the results here differ, but ours are correct.
45 ?x@@3PEAHEA
46 ; CHECK: int *x
47
48 ?x@@3PEBHEB
49 ; CHECK: int const *x
50
51 ?x@@3QEAHEA
52 ; CHECK: int *const x
53
54 ?x@@3QEBHEB
55 ; CHECK: int const *const x
56
57
58 ?x@@3AEBHEB
59 ; CHECK: int const &x
60
61 ?x@@3PEAUty@@EA
62 ; CHECK: struct ty *x
63
64 ?x@@3PEATty@@EA
65 ; CHECK: union ty *x
66
67 ?x@@3PEAUty@@EA
68 ; CHECK: struct ty *x
69
70 ?x@@3PEAW4ty@@EA
71 ; CHECK: enum ty *x
72
73 ?x@@3PEAVty@@EA
74 ; CHECK: class ty *x
75
76 ?x@@3PEAV?$tmpl@H@@EA
77 ; CHECK: class tmpl *x
78
79 ?x@@3PEAU?$tmpl@H@@EA
80 ; CHECK: struct tmpl *x
81
82 ?x@@3PEAT?$tmpl@H@@EA
83 ; CHECK: union tmpl *x
84
85 ?instance@@3Vklass@@A
86 ; CHECK: class klass instance
87
88 ?instance$initializer$@@3P6AXXZEA
89 ; CHECK: void __cdecl (*instance$initializer$)(void)
90
91 ??0klass@@QEAA@XZ
92 ; CHECK: __cdecl klass::klass(void)
93
94 ??1klass@@QEAA@XZ
95 ; CHECK: __cdecl klass::~klass(void)
96
97 ?x@@YAHPEAVklass@@AEAV1@@Z
98 ; CHECK: int __cdecl x(class klass *, class klass &)
99
100 ?x@ns@@3PEAV?$klass@HH@1@EA
101 ; CHECK: class ns::klass *ns::x
102
103 ?fn@?$klass@H@ns@@QEBAIXZ
104 ; CHECK: unsigned int __cdecl ns::klass::fn(void) const
105
106
107 ??4klass@@QEAAAEBV0@AEBV0@@Z
108 ; CHECK: class klass const &__cdecl klass::operator=(class klass const &)
109
110 ??7klass@@QEAA_NXZ
111 ; CHECK: bool __cdecl klass::operator!(void)
112
113 ??8klass@@QEAA_NAEBV0@@Z
114 ; CHECK: bool __cdecl klass::operator==(class klass const &)
115
116 ??9klass@@QEAA_NAEBV0@@Z
117 ; CHECK: bool __cdecl klass::operator!=(class klass const &)
118
119 ??Aklass@@QEAAH_K@Z
120 ; CHECK: int __cdecl klass::operator[](unsigned __int64)
121
122 ??Cklass@@QEAAHXZ
123 ; CHECK: int __cdecl klass::operator->(void)
124
125 ??Dklass@@QEAAHXZ
126 ; CHECK: int __cdecl klass::operator*(void)
127
128 ??Eklass@@QEAAHXZ
129 ; CHECK: int __cdecl klass::operator++(void)
130
131 ??Eklass@@QEAAHH@Z
132 ; CHECK: int __cdecl klass::operator++(int)
133
134 ??Fklass@@QEAAHXZ
135 ; CHECK: int __cdecl klass::operator--(void)
136
137 ??Fklass@@QEAAHH@Z
138 ; CHECK: int __cdecl klass::operator--(int)
139
140 ??Hklass@@QEAAHH@Z
141 ; CHECK: int __cdecl klass::operator+(int)
142
143 ??Gklass@@QEAAHH@Z
144 ; CHECK: int __cdecl klass::operator-(int)
145
146 ??Iklass@@QEAAHH@Z
147 ; CHECK: int __cdecl klass::operator&(int)
148
149 ??Jklass@@QEAAHH@Z
150 ; CHECK: int __cdecl klass::operator->*(int)
151
152 ??Kklass@@QEAAHH@Z
153 ; CHECK: int __cdecl klass::operator/(int)
154
155 ??Mklass@@QEAAHH@Z
156 ; CHECK: int __cdecl klass::operator<(int)
157
158 ??Nklass@@QEAAHH@Z
159 ; CHECK: int __cdecl klass::operator<=(int)
160
161 ??Oklass@@QEAAHH@Z
162 ; CHECK: int __cdecl klass::operator>(int)
163
164 ??Pklass@@QEAAHH@Z
165 ; CHECK: int __cdecl klass::operator>=(int)
166
167 ??Qklass@@QEAAHH@Z
168 ; CHECK: int __cdecl klass::operator,(int)
169
170 ??Rklass@@QEAAHH@Z
171 ; CHECK: int __cdecl klass::operator()(int)
172
173 ??Sklass@@QEAAHXZ
174 ; CHECK: int __cdecl klass::operator~(void)
175
176 ??Tklass@@QEAAHH@Z
177 ; CHECK: int __cdecl klass::operator^(int)
178
179 ??Uklass@@QEAAHH@Z
180 ; CHECK: int __cdecl klass::operator|(int)
181
182 ??Vklass@@QEAAHH@Z
183 ; CHECK: int __cdecl klass::operator&&(int)
184
185 ??Wklass@@QEAAHH@Z
186 ; CHECK: int __cdecl klass::operator||(int)
187
188 ??Xklass@@QEAAHH@Z
189 ; CHECK: int __cdecl klass::operator*=(int)
190
191 ??Yklass@@QEAAHH@Z
192 ; CHECK: int __cdecl klass::operator+=(int)
193
194 ??Zklass@@QEAAHH@Z
195 ; CHECK: int __cdecl klass::operator-=(int)
196
197 ??_0klass@@QEAAHH@Z
198 ; CHECK: int __cdecl klass::operator/=(int)
199
200 ??_1klass@@QEAAHH@Z
201 ; CHECK: int __cdecl klass::operator%=(int)
202
203 ??_2klass@@QEAAHH@Z
204 ; CHECK: int __cdecl klass::operator>>=(int)
205
206 ??_3klass@@QEAAHH@Z
207 ; CHECK: int __cdecl klass::operator<<=(int)
208
209 ??_6klass@@QEAAHH@Z
210 ; CHECK: int __cdecl klass::operator^=(int)
211
212 ??6@YAAEBVklass@@AEBV0@H@Z
213 ; CHECK: class klass const &__cdecl operator<<(class klass const &, int)
214
215 ??5@YAAEBVklass@@AEBV0@_K@Z
216 ; CHECK: class klass const &__cdecl operator>>(class klass const &, unsigned __int64)
217
218 ??2@YAPEAX_KAEAVklass@@@Z
219 ; CHECK: void *__cdecl operator new(unsigned __int64, class klass &)
220
221 ??_U@YAPEAX_KAEAVklass@@@Z
222 ; CHECK: void *__cdecl operator new[](unsigned __int64, class klass &)
223
224 ??3@YAXPEAXAEAVklass@@@Z
225 ; CHECK: void __cdecl operator delete(void *, class klass &)
226
227 ??_V@YAXPEAXAEAVklass@@@Z
228 ; CHECK: void __cdecl operator delete[](void *, class klass &)
229
0 ; These tests are based on clang/test/CodeGenCXX/mangle-ms.cpp
1 ; RUN: llvm-undname < %s | FileCheck %s
2
3 ; CHECK-NOT: Invalid mangled name
4
5 ?k@@3PTfoo@@DT1
6
7
8 ?a@@3HA
9 ; CHECK: int a
10
11 ?b@N@@3HA
12 ; CHECK: int N::b
13
14 ?anonymous@?A@N@@3HA
15 ; CHECK: int N::`anonymous namespace'::anonymous
16
17 ?_c@@YAHXZ
18 ; CHECK: int __cdecl _c(void)
19
20 ?d@foo@@0FB
21 ; CHECK: static short const foo::d
22
23 ?e@foo@@1JC
24 ; CHECK: static long volatile foo::e
25
26 ?f@foo@@2DD
27 ; CHECK: static char const volatile foo::f
28
29 ??0foo@@QAE@XZ
30 ; CHECK: __thiscall foo::foo(void)
31
32 ??0foo@@QEAA@XZ
33 ; CHECK: __cdecl foo::foo(void)
34
35 ??1foo@@QAE@XZ
36 ; CHECK: __thiscall foo::~foo(void)
37
38 ??1foo@@QEAA@XZ
39 ; CHECK: __cdecl foo::~foo(void)
40
41 ??0foo@@QAE@H@Z
42 ; CHECK: __thiscall foo::foo(int)
43
44 ??0foo@@QEAA@H@Z
45 ; CHECK: __cdecl foo::foo(int)
46
47 ??0foo@@QAE@PAD@Z
48 ; CHECK: __thiscall foo::foo(char *)
49
50 ??0foo@@QEAA@PEAD@Z
51 ; CHECK: __cdecl foo::foo(char *)
52
53 ?bar@@YA?AVfoo@@XZ
54 ; CHECK: class foo __cdecl bar(void)
55
56 ?bar@@YA?AVfoo@@XZ
57 ; CHECK: class foo __cdecl bar(void)
58
59 ??Hfoo@@QAEHH@Z
60 ; CHECK: int __thiscall foo::operator+(int)
61
62 ??Hfoo@@QEAAHH@Z
63 ; CHECK: int __cdecl foo::operator+(int)
64
65 ?static_method@foo@@SAPAV1@XZ
66 ; CHECK: static class foo *__cdecl foo::static_method(void)
67
68 ?static_method@foo@@SAPEAV1@XZ
69 ; CHECK: static class foo *__cdecl foo::static_method(void)
70
71 ?g@bar@@2HA
72 ; CHECK: static int bar::g
73
74 ; undname returns `int *h1`, but it is a bug in their demangler. Their mangler
75 ; correctly mangles `int *h1` as ?h1@3PAHA and `int * const h1` as ?h1@3QAHA
76 ?h1@@3QAHA
77 ; CHECK: int *const h1
78
79 ?h2@@3QBHB
80 ; CHECK: int const *const h2
81
82 ?h3@@3QIAHIA
83 ; CHECK: int * __restrict const h3
84
85 ?h3@@3QEIAHEIA
86 ; CHECK: int * __restrict const h3
87
88 ?i@@3PAY0BE@HA
89 ; CHECK: int (*i)[20]
90
91 ?FunArr@@3PAY0BE@P6AHHH@ZA
92 ; CHECK: int __cdecl (*(*FunArr)[20])(int, int)
93
94 ?j@@3P6GHCE@ZA
95 ; CHECK: int __stdcall (*j)(signed char, unsigned char)
96
97
98 ; FIXME: We don't handle member pointers yet.
99 ; ?k@@3PTfoo@@DT1
100 ; FIXME: char const volatile foo::*k
101
102 ; ?k@@3PETfoo@@DET1
103 ; FIXME: char const volatile foo::*k
104
105 ; ?l@@3P8foo@@AEHH@ZQ1
106 ; FIXME: int __thiscall (foo::*l)(int)
107
108 ?g_cInt@@3HB
109 ; CHECK: int const g_cInt
110
111 ?g_vInt@@3HC
112 ; CHECK: int volatile g_vInt
113
114 ?g_cvInt@@3HD
115 ; CHECK: int const volatile g_cvInt
116
117 ?beta@@YI_N_J_W@Z
118 ; CHECK: bool __fastcall beta(__int64, wchar_t)
119
120 ?beta@@YA_N_J_W@Z
121 ; CHECK: bool __cdecl beta(__int64, wchar_t)
122
123 ?alpha@@YGXMN@Z
124 ; CHECK: void __stdcall alpha(float, double)
125
126 ?alpha@@YAXMN@Z
127 ; CHECK: void __cdecl alpha(float, double)
128
129 ?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z
130 ; CHECK: void __cdecl gamma(class foo, struct bar, union baz, enum quux)
131
132 ?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z
133 ; CHECK: void __cdecl gamma(class foo, struct bar, union baz, enum quux)
134
135 ?delta@@YAXQAHABJ@Z
136 ; CHECK: void __cdecl delta(int *const, long const &)
137
138 ?delta@@YAXQEAHAEBJ@Z
139 ; CHECK: void __cdecl delta(int *const, long const &)
140
141 ?epsilon@@YAXQAY19BE@H@Z
142 ; CHECK: void __cdecl epsilon(int (*const)[10][20])
143
144 ?epsilon@@YAXQEAY19BE@H@Z
145 ; CHECK: void __cdecl epsilon(int (*const)[10][20])
146
147 ?zeta@@YAXP6AHHH@Z@Z
148 ; CHECK: void __cdecl zeta(int __cdecl (*)(int, int))
149
150 ?zeta@@YAXP6AHHH@Z@Z
151 ; CHECK: void __cdecl zeta(int __cdecl (*)(int, int))
152
153 ??2@YAPAXI@Z
154 ; CHECK: void *__cdecl operator new(unsigned int)
155
156 ??3@YAXPAX@Z
157 ; CHECK: void __cdecl operator delete(void *)
158
159 ??_U@YAPAXI@Z
160 ; CHECK: void *__cdecl operator new[](unsigned int)
161
162 ??_V@YAXPAX@Z
163 ; CHECK: void __cdecl operator delete[](void *)
164
165 ?color1@@3PANA
166 ; CHECK: double *color1
167
168 ?color2@@3QBNB
169 ; CHECK: double const *const color2
170
171 ; FIXME-EXTRACONST: These tests fails because we print an extra const inside the parens.
172 ; ?color3@@3QAY02$$CBNA
173 ; FIXME-EXTRACONST: double const (*color3)[3]
174
175 ; ?color4@@3QAY02$$CBNA
176 ; FIXME-EXTRACONST: double const (*color4)[3]
177
178 ; FIXME-MEMBERPTR: We don't support member pointers yet.
179 ; ?memptr1@@3RESB@@HES1
180 ; FIXME-MEMBERPTR: volatile int B::*memptr2
181
182 ; ?memptr2@@3PESB@@HES1
183 ; FIXME: volatile int B::*memptr2
184
185 ; ?memptr3@@3REQB@@HEQ1
186 ; FIXME-MEMBERPTR: int B::* volatile memptr3
187
188 ; ?funmemptr1@@3RESB@@R6AHXZES1
189 ; FIXME-MEMBERPTR: int __cdecl (* volatile B::* volatile funmemptr1)(void)
190
191 ; ?funmemptr2@@3PESB@@R6AHXZES1
192 ; FIXME-MEMBERPTR: int __cdecl (* volatile B::*funmemptr2)(void)
193
194 ; ?funmemptr3@@3REQB@@P6AHXZEQ1
195 ; FIXME-MEMBERPTR: int __cdecl (* B::*volatile funmemptr3)(void)
196
197 ; ?memptrtofun1@@3R8B@@EAAXXZEQ1
198 ; FIXME-MEMBERPTR: void __cdecl (B::*volatile memptrtofun1)(void)
199
200 ; ?memptrtofun2@@3P8B@@EAAXXZEQ1
201 ; FIXME-MEMBERPTR: void __cdecl (B::*memptrtofun2)(void)
202
203 ; ?memptrtofun3@@3P8B@@EAAXXZEQ1
204 ; FIXME-MEMBERPTR: void __cdecl (B::*memptrtofun3)(void)
205
206 ; ?memptrtofun4@@3R8B@@EAAHXZEQ1
207 ; FIXME-MEMBERPTR: int __cdecl (B::* volatile memptrtofun4)(void)
208
209 ; ?memptrtofun5@@3P8B@@EAA?CHXZEQ1
210 ; FIXME-MEMBERPTR: int volatile __cdecl (B::*memptrtofun5)(void)
211
212 ; ?memptrtofun6@@3P8B@@EAA?BHXZEQ1
213 ; FIXME-MEMBERPTR: int const __cdecl (B::*memptrtofun6)(void)
214
215 ; ?memptrtofun7@@3R8B@@EAAP6AHXZXZEQ1
216 ; FIXME-MEMBERPTR: int __cdecl (*(__cdecl B::*volatile memptrtofun7)(void))(void)
217
218 ; ?memptrtofun8@@3P8B@@EAAR6AHXZXZEQ1
219 ; FIXME-MEMBERPTR: int __cdecl (*(__cdecl B::*memptrtofun8)(void))(void)
220
221 ; ?memptrtofun9@@3P8B@@EAAQ6AHXZXZEQ1
222 ; FIXME-MEMBERPTR: int __cdecl(*(__cdecl B::*memptrtofun9)(void))(void)
223
224
225 ?fooE@@YA?AW4E@@XZ
226 ; CHECK: enum E __cdecl fooE(void)
227
228 ?fooE@@YA?AW4E@@XZ
229 ; CHECK: enum E __cdecl fooE(void)
230
231 ?fooX@@YA?AVX@@XZ
232 ; CHECK: class X __cdecl fooX(void)
233
234 ?fooX@@YA?AVX@@XZ
235 ; CHECK: class X __cdecl fooX(void)
236
237 ?s0@PR13182@@3PADA
238 ; CHECK: char *PR13182::s0
239
240 ?s1@PR13182@@3PADA
241 ; CHECK: char *PR13182::s1
242
243 ?s2@PR13182@@3QBDB
244 ; CHECK: char const *const PR13182::s2
245
246 ?s3@PR13182@@3QBDB
247 ; CHECK: char const *const PR13182::s3
248
249 ?s4@PR13182@@3RCDC
250 ; CHECK: char volatile *volatile PR13182::s4
251
252 ?s5@PR13182@@3SDDD
253 ; CHECK: char const volatile *const volatile PR13182::s5
254
255 ; undname adds an extra const in here, but it seems like their bug.
256 ?s6@PR13182@@3PBQBDB
257 ; CHECK: char const *const *PR13182::s6
258
259 ; FIXME-EXTERNC: We don't properly support static locals in extern c functions yet.
260 ; ?local@?1??extern_c_func@@9@4HA
261 ; FIXME-EXTERNC: int `extern_c_func'::`2'::local
262
263 ; ?local@?1??extern_c_func@@9@4HA
264 ; FIXME-EXTERNC: int `extern_c_func'::`2'::local
265
266 ??2OverloadedNewDelete@@SAPAXI@Z
267 ; CHECK: static void *__cdecl OverloadedNewDelete::operator new(unsigned int)
268
269
270 ??_UOverloadedNewDelete@@SAPAXI@Z
271 ; CHECK: static void *__cdecl OverloadedNewDelete::operator new[](unsigned int)
272
273 ??3OverloadedNewDelete@@SAXPAX@Z
274 ; CHECK: static void __cdecl OverloadedNewDelete::operator delete(void *)
275
276
277 ??_VOverloadedNewDelete@@SAXPAX@Z
278 ; CHECK: static void __cdecl OverloadedNewDelete::operator delete[](void *)
279
280 ??HOverloadedNewDelete@@QAEHH@Z
281 ; CHECK: int __thiscall OverloadedNewDelete::operator+(int)
282
283 ??2OverloadedNewDelete@@SAPEAX_K@Z
284 ; CHECK: static void *__cdecl OverloadedNewDelete::operator new(unsigned __int64)
285
286 ??_UOverloadedNewDelete@@SAPEAX_K@Z
287 ; CHECK: static void *__cdecl OverloadedNewDelete::operator new[](unsigned __int64)
288
289 ??3OverloadedNewDelete@@SAXPEAX@Z
290 ; CHECK: static void __cdecl OverloadedNewDelete::operator delete(void *)
291
292
293 ??_VOverloadedNewDelete@@SAXPEAX@Z
294 ; CHECK: static void __cdecl OverloadedNewDelete::operator delete[](void *)
295
296 ??HOverloadedNewDelete@@QEAAHH@Z
297 ; CHECK: int __cdecl OverloadedNewDelete::operator+(int)
298
299
300 ??2TypedefNewDelete@@SAPAXI@Z
301 ; CHECK: static void *__cdecl TypedefNewDelete::operator new(unsigned int)
302
303
304 ??_UTypedefNewDelete@@SAPAXI@Z
305 ; CHECK: static void *__cdecl TypedefNewDelete::operator new[](unsigned int)
306
307 ??3TypedefNewDelete@@SAXPAX@Z
308 ; CHECK: static void __cdecl TypedefNewDelete::operator delete(void *)
309
310 ??_VTypedefNewDelete@@SAXPAX@Z
311 ; CHECK: static void __cdecl TypedefNewDelete::operator delete[](void *)
312
313 ?vector_func@@YQXXZ
314 ; CHECK: void __vectorcall vector_func(void)
315
316 ; FIXME-EXTERNC: We don't support extern C funcs currently.
317 ; ??$fn_tmpl@$1?extern_c_func@@YAXXZ@@YAXXZ
318 ; FIXME-EXTERNC: void __cdecl fn_tmpl<&void __cdecl extern_c_func(void)>(void)
319
320 ; ?overloaded_fn@@$$J0YAXXZ
321 ; FIXME-EXTERNC: extern \"C\" void __cdecl overloaded_fn(void)
322
323
324 ?f@UnnamedType@@YAXUT2@S@1@@Z
325 ; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T2)
326
327 ?f@UnnamedType@@YAXPAUT4@S@1@@Z
328 ; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T4 *)
329
330 ?f@UnnamedType@@YAXUT4@S@1@@Z
331 ; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T4)
332
333 ?f@UnnamedType@@YAXUT5@S@1@@Z
334 ; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T5)
335
336 ?f@UnnamedType@@YAXUT2@S@1@@Z
337 ; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T2)
338
339 ?f@UnnamedType@@YAXUT4@S@1@@Z
340 ; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T4)
341
342 ?f@UnnamedType@@YAXUT5@S@1@@Z
343 ; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T5)
344
345 ?f@Atomic@@YAXU?$_Atomic@H@__clang@@@Z
346 ; CHECK: void __cdecl Atomic::f(struct __clang::_Atomic)
347
348 ?f@Complex@@YAXU?$_Complex@H@__clang@@@Z
349 ; CHECK: void __cdecl Complex::f(struct __clang::_Complex)
350
351 ?f@Float16@@YAXU_Float16@__clang@@@Z
352 ; CHECK: void __cdecl Float16::f(struct __clang::_Float16)
353
354
355 ??0?$L@H@NS@@QEAA@XZ
356 ; CHECK: __cdecl NS::L::L(void)
357
358 ??0Bar@Foo@@QEAA@XZ
359 ; CHECK: __cdecl Foo::Bar::Bar(void)
360
361 ??0?$L@V?$H@PAH@PR26029@@@PR26029@@QAE@XZ
362 ; CHECK: __thiscall PR26029::L>::L>(void)
0 ; See clang/test/CodeGenCXX/mangle-windows.cpp
1 ; These tests are based on clang/test/CodeGenCXX/mangle-ms.cpp
2 ; RUN: llvm-undname < %s | FileCheck %s
3
4 ; CHECK-NOT: Invalid mangled name
5
6 ?bar@Foo@@SGXXZ
7 ; CHECK: static void __stdcall Foo::bar(void)
8
9 ?bar@Foo@@QAGXXZ
10 ; CHECK: void __stdcall Foo::bar(void)
11
12 ?f2@@YIXXZ
13 ; CHECK: void __fastcall f2(void)
14
15 ?f1@@YGXXZ
16 ; CHECK: void __stdcall f1(void)
4949 llvm-rtdyld
5050 llvm-size
5151 llvm-split
52 llvm-undname
5253 opt
5354 verify-uselistorder
5455
0 set(LLVM_LINK_COMPONENTS
1 Demangle
2 Support
3 )
4
5 add_llvm_tool(llvm-undname
6 llvm-undname.cpp
7 )
0 ;===- ./tools/llvm-undname/LLVMBuild.txt -----------------------*- Conf -*--===;
1 ;
2 ; The LLVM Compiler Infrastructure
3 ;
4 ; This file is distributed under the University of Illinois Open Source
5 ; License. See LICENSE.TXT for details.
6 ;
7 ;===------------------------------------------------------------------------===;
8 ;
9 ; This is an LLVMBuild description file for the components in this subdirectory.
10 ;
11 ; For more information on the LLVMBuild system, please see:
12 ;
13 ; http://llvm.org/docs/LLVMBuild.html
14 ;
15 ;===------------------------------------------------------------------------===;
16
17 [component_0]
18 type = Tool
19 name = llvm-undname
20 parent = Tools
21 required_libraries = Demangle Support
22
0 //===-- llvm-undname.cpp - Microsoft ABI name undecorator
1 //------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This utility works like the windows undname utility. It converts mangled
11 // Microsoft symbol names into pretty C/C++ human-readable names.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Demangle/Demangle.h"
17 #include "llvm/Support/CommandLine.h"
18 #include "llvm/Support/InitLLVM.h"
19 #include "llvm/Support/Process.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include
22 #include
23 #include
24 #include
25
26 using namespace llvm;
27
28 cl::list Symbols(cl::Positional, cl::desc(""),
29 cl::ZeroOrMore);
30
31 static void demangle(const std::string &S) {
32 int Status;
33 char *ResultBuf = microsoftDemangle(S.c_str(), nullptr, nullptr, &Status);
34 if (Status == llvm::demangle_success) {
35 outs() << ResultBuf << "\n";
36 outs().flush();
37 } else {
38 errs() << "Error: Invalid mangled name\n";
39 }
40 std::free(ResultBuf);
41 };
42
43 int main(int argc, char **argv) {
44 InitLLVM X(argc, argv);
45
46 cl::ParseCommandLineOptions(argc, argv, "llvm-undname\n");
47
48 if (Symbols.empty()) {
49 while (true) {
50 std::string LineStr;
51 std::getline(std::cin, LineStr);
52 if (std::cin.eof())
53 break;
54
55 StringRef Line(LineStr);
56 Line = Line.trim();
57 if (Line.empty() || Line.startswith("#") || Line.startswith(";"))
58 continue;
59
60 // If the user is manually typing in these decorated names, don't echo
61 // them to the terminal a second time. If they're coming from redirected
62 // input, however, then we should display the input line so that the
63 // mangled and demangled name can be easily correlated in the output.
64 if (!sys::Process::StandardInIsUserInput())
65 outs() << Line << "\n";
66 demangle(Line);
67 outs() << "\n";
68 }
69 } else {
70 for (StringRef S : Symbols) {
71 outs() << S << "\n";
72 demangle(S);
73 outs() << "\n";
74 }
75 }
76
77 return 0;
78 }