File: | lib/Demangle/MicrosoftDemangle.cpp |
Warning: | line 1613, column 22 Dereference of undefined pointer value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- MicrosoftDemangle.cpp ----------------------------------------------===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is dual licensed under the MIT and the University of Illinois Open | |||
6 | // Source Licenses. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | // | |||
10 | // This file defines a demangler for MSVC-style mangled symbols. | |||
11 | // | |||
12 | // This file has no dependencies on the rest of LLVM so that it can be | |||
13 | // easily reused in other programs such as libcxxabi. | |||
14 | // | |||
15 | //===----------------------------------------------------------------------===// | |||
16 | ||||
17 | #include "llvm/Demangle/Demangle.h" | |||
18 | ||||
19 | #include "Compiler.h" | |||
20 | #include "StringView.h" | |||
21 | #include "Utility.h" | |||
22 | ||||
23 | #include <cctype> | |||
24 | #include <tuple> | |||
25 | ||||
26 | // This memory allocator is extremely fast, but it doesn't call dtors | |||
27 | // for allocated objects. That means you can't use STL containers | |||
28 | // (such as std::vector) with this allocator. But it pays off -- | |||
29 | // the demangler is 3x faster with this allocator compared to one with | |||
30 | // STL containers. | |||
31 | namespace { | |||
32 | class ArenaAllocator { | |||
33 | struct AllocatorNode { | |||
34 | uint8_t *Buf = nullptr; | |||
35 | size_t Used = 0; | |||
36 | AllocatorNode *Next = nullptr; | |||
37 | }; | |||
38 | ||||
39 | public: | |||
40 | ArenaAllocator() : Head(new AllocatorNode) { Head->Buf = new uint8_t[Unit]; } | |||
41 | ||||
42 | ~ArenaAllocator() { | |||
43 | while (Head) { | |||
44 | assert(Head->Buf)(static_cast <bool> (Head->Buf) ? void (0) : __assert_fail ("Head->Buf", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 44, __extension__ __PRETTY_FUNCTION__)); | |||
45 | delete[] Head->Buf; | |||
46 | AllocatorNode *Next = Head->Next; | |||
47 | delete Head; | |||
48 | Head = Next; | |||
49 | } | |||
50 | } | |||
51 | ||||
52 | template <typename T, typename... Args> T *alloc(Args &&... ConstructorArgs) { | |||
53 | ||||
54 | size_t Size = sizeof(T); | |||
55 | assert(Size < Unit)(static_cast <bool> (Size < Unit) ? void (0) : __assert_fail ("Size < Unit", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 55, __extension__ __PRETTY_FUNCTION__)); | |||
56 | assert(Head && Head->Buf)(static_cast <bool> (Head && Head->Buf) ? void (0) : __assert_fail ("Head && Head->Buf", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 56, __extension__ __PRETTY_FUNCTION__)); | |||
57 | ||||
58 | size_t P = (size_t)Head->Buf + Head->Used; | |||
59 | uintptr_t AlignedP = | |||
60 | (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1)); | |||
61 | uint8_t *PP = (uint8_t *)AlignedP; | |||
62 | size_t Adjustment = AlignedP - P; | |||
63 | ||||
64 | Head->Used += Size + Adjustment; | |||
65 | if (Head->Used < Unit) | |||
66 | return new (PP) T(std::forward<Args>(ConstructorArgs)...); | |||
67 | ||||
68 | AllocatorNode *NewHead = new AllocatorNode; | |||
69 | NewHead->Buf = new uint8_t[ArenaAllocator::Unit]; | |||
70 | NewHead->Next = Head; | |||
71 | Head = NewHead; | |||
72 | NewHead->Used = Size; | |||
73 | return new (NewHead->Buf) T(std::forward<Args>(ConstructorArgs)...); | |||
74 | } | |||
75 | ||||
76 | private: | |||
77 | static constexpr size_t Unit = 4096; | |||
78 | ||||
79 | AllocatorNode *Head = nullptr; | |||
80 | }; | |||
81 | } // namespace | |||
82 | ||||
83 | static bool startsWithDigit(StringView S) { | |||
84 | return !S.empty() && std::isdigit(S.front()); | |||
85 | } | |||
86 | ||||
87 | // Writes a space if the last token does not end with a punctuation. | |||
88 | static void outputSpaceIfNecessary(OutputStream &OS) { | |||
89 | if (OS.empty()) | |||
90 | return; | |||
91 | ||||
92 | char C = OS.back(); | |||
93 | if (isalnum(C) || C == '>') | |||
94 | OS << " "; | |||
95 | } | |||
96 | ||||
97 | // Storage classes | |||
98 | enum Qualifiers : uint8_t { | |||
99 | Q_None = 0, | |||
100 | Q_Const = 1 << 0, | |||
101 | Q_Volatile = 1 << 1, | |||
102 | Q_Far = 1 << 2, | |||
103 | Q_Huge = 1 << 3, | |||
104 | Q_Unaligned = 1 << 4, | |||
105 | Q_Restrict = 1 << 5, | |||
106 | Q_Pointer64 = 1 << 6 | |||
107 | }; | |||
108 | ||||
109 | enum class StorageClass : uint8_t { | |||
110 | None, | |||
111 | PrivateStatic, | |||
112 | ProtectedStatic, | |||
113 | PublicStatic, | |||
114 | Global, | |||
115 | FunctionLocalStatic | |||
116 | }; | |||
117 | ||||
118 | enum class QualifierMangleMode { Drop, Mangle, Result }; | |||
119 | ||||
120 | enum class PointerAffinity { Pointer, Reference }; | |||
121 | ||||
122 | // Calling conventions | |||
123 | enum class CallingConv : uint8_t { | |||
124 | None, | |||
125 | Cdecl, | |||
126 | Pascal, | |||
127 | Thiscall, | |||
128 | Stdcall, | |||
129 | Fastcall, | |||
130 | Clrcall, | |||
131 | Eabi, | |||
132 | Vectorcall, | |||
133 | Regcall, | |||
134 | }; | |||
135 | ||||
136 | enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef }; | |||
137 | ||||
138 | // Types | |||
139 | enum class PrimTy : uint8_t { | |||
140 | Unknown, | |||
141 | None, | |||
142 | Function, | |||
143 | Ptr, | |||
144 | Ref, | |||
145 | MemberPtr, | |||
146 | Array, | |||
147 | ||||
148 | Struct, | |||
149 | Union, | |||
150 | Class, | |||
151 | Enum, | |||
152 | ||||
153 | Void, | |||
154 | Bool, | |||
155 | Char, | |||
156 | Schar, | |||
157 | Uchar, | |||
158 | Short, | |||
159 | Ushort, | |||
160 | Int, | |||
161 | Uint, | |||
162 | Long, | |||
163 | Ulong, | |||
164 | Int64, | |||
165 | Uint64, | |||
166 | Wchar, | |||
167 | Float, | |||
168 | Double, | |||
169 | Ldouble, | |||
170 | }; | |||
171 | ||||
172 | // Function classes | |||
173 | enum FuncClass : uint8_t { | |||
174 | Public = 1 << 0, | |||
175 | Protected = 1 << 1, | |||
176 | Private = 1 << 2, | |||
177 | Global = 1 << 3, | |||
178 | Static = 1 << 4, | |||
179 | Virtual = 1 << 5, | |||
180 | Far = 1 << 6, | |||
181 | }; | |||
182 | ||||
183 | namespace { | |||
184 | ||||
185 | struct Type; | |||
186 | ||||
187 | // Represents a list of parameters (template params or function arguments. | |||
188 | // It's represented as a linked list. | |||
189 | struct ParamList { | |||
190 | bool IsVariadic = false; | |||
191 | ||||
192 | Type *Current = nullptr; | |||
193 | ||||
194 | ParamList *Next = nullptr; | |||
195 | }; | |||
196 | ||||
197 | // The type class. Mangled symbols are first parsed and converted to | |||
198 | // this type and then converted to string. | |||
199 | struct Type { | |||
200 | virtual ~Type() {} | |||
201 | ||||
202 | virtual Type *clone(ArenaAllocator &Arena) const; | |||
203 | ||||
204 | // Write the "first half" of a given type. This is a static functions to | |||
205 | // give the code a chance to do processing that is common to a subset of | |||
206 | // subclasses | |||
207 | static void outputPre(OutputStream &OS, Type &Ty); | |||
208 | ||||
209 | // Write the "second half" of a given type. This is a static functions to | |||
210 | // give the code a chance to do processing that is common to a subset of | |||
211 | // subclasses | |||
212 | static void outputPost(OutputStream &OS, Type &Ty); | |||
213 | ||||
214 | virtual void outputPre(OutputStream &OS); | |||
215 | virtual void outputPost(OutputStream &OS); | |||
216 | ||||
217 | // Primitive type such as Int. | |||
218 | PrimTy Prim = PrimTy::Unknown; | |||
219 | ||||
220 | Qualifiers Quals = Q_None; | |||
221 | StorageClass Storage = StorageClass::None; // storage class | |||
222 | }; | |||
223 | ||||
224 | // Represents an identifier which may be a template. | |||
225 | struct Name { | |||
226 | // Name read from an MangledName string. | |||
227 | StringView Str; | |||
228 | ||||
229 | // Overloaded operators are represented as special BackReferences in mangled | |||
230 | // symbols. If this is an operator name, "op" has an operator name (e.g. | |||
231 | // ">>"). Otherwise, empty. | |||
232 | StringView Operator; | |||
233 | ||||
234 | // Template parameters. Null if not a template. | |||
235 | ParamList TemplateParams; | |||
236 | ||||
237 | // Nested BackReferences (e.g. "A::B::C") are represented as a linked list. | |||
238 | Name *Next = nullptr; | |||
239 | }; | |||
240 | ||||
241 | struct PointerType : public Type { | |||
242 | Type *clone(ArenaAllocator &Arena) const override; | |||
243 | void outputPre(OutputStream &OS) override; | |||
244 | void outputPost(OutputStream &OS) override; | |||
245 | ||||
246 | // Represents a type X in "a pointer to X", "a reference to X", | |||
247 | // "an array of X", or "a function returning X". | |||
248 | Type *Pointee = nullptr; | |||
249 | }; | |||
250 | ||||
251 | struct MemberPointerType : public Type { | |||
252 | Type *clone(ArenaAllocator &Arena) const override; | |||
253 | void outputPre(OutputStream &OS) override; | |||
254 | void outputPost(OutputStream &OS) override; | |||
255 | ||||
256 | Name *MemberName = nullptr; | |||
257 | ||||
258 | // Represents a type X in "a pointer to X", "a reference to X", | |||
259 | // "an array of X", or "a function returning X". | |||
260 | Type *Pointee = nullptr; | |||
261 | }; | |||
262 | ||||
263 | struct FunctionType : public Type { | |||
264 | Type *clone(ArenaAllocator &Arena) const override; | |||
265 | void outputPre(OutputStream &OS) override; | |||
266 | void outputPost(OutputStream &OS) override; | |||
267 | ||||
268 | // True if this FunctionType instance is the Pointee of a PointerType or | |||
269 | // MemberPointerType. | |||
270 | bool IsFunctionPointer = false; | |||
271 | ||||
272 | Type *ReturnType = nullptr; | |||
273 | // If this is a reference, the type of reference. | |||
274 | ReferenceKind RefKind; | |||
275 | ||||
276 | CallingConv CallConvention; | |||
277 | FuncClass FunctionClass; | |||
278 | ||||
279 | ParamList Params; | |||
280 | }; | |||
281 | ||||
282 | struct UdtType : public Type { | |||
283 | Type *clone(ArenaAllocator &Arena) const override; | |||
284 | void outputPre(OutputStream &OS) override; | |||
285 | ||||
286 | Name *UdtName = nullptr; | |||
287 | }; | |||
288 | ||||
289 | struct ArrayType : public Type { | |||
290 | Type *clone(ArenaAllocator &Arena) const override; | |||
291 | void outputPre(OutputStream &OS) override; | |||
292 | void outputPost(OutputStream &OS) override; | |||
293 | ||||
294 | // Either NextDimension or ElementType will be valid. | |||
295 | ArrayType *NextDimension = nullptr; | |||
296 | uint32_t ArrayDimension = 0; | |||
297 | ||||
298 | Type *ElementType = nullptr; | |||
299 | }; | |||
300 | ||||
301 | } // namespace | |||
302 | ||||
303 | static bool isMemberPointer(StringView MangledName) { | |||
304 | switch (MangledName.popFront()) { | |||
305 | case 'A': | |||
306 | // 'A' indicates a reference, and you cannot have a reference to a member | |||
307 | // function or member variable. | |||
308 | return false; | |||
309 | case 'P': | |||
310 | case 'Q': | |||
311 | case 'R': | |||
312 | case 'S': | |||
313 | // These 4 values indicate some kind of pointer, but we still don't know | |||
314 | // what. | |||
315 | break; | |||
316 | default: | |||
317 | assert(false && "Ty is not a pointer type!")(static_cast <bool> (false && "Ty is not a pointer type!" ) ? void (0) : __assert_fail ("false && \"Ty is not a pointer type!\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 317, __extension__ __PRETTY_FUNCTION__)); | |||
318 | } | |||
319 | ||||
320 | // If it starts with a number, then 6 indicates a non-member function | |||
321 | // pointer, and 8 indicates a member function pointer. | |||
322 | if (startsWithDigit(MangledName)) { | |||
323 | assert(MangledName[0] == '6' || MangledName[0] == '8')(static_cast <bool> (MangledName[0] == '6' || MangledName [0] == '8') ? void (0) : __assert_fail ("MangledName[0] == '6' || MangledName[0] == '8'" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 323, __extension__ __PRETTY_FUNCTION__)); | |||
324 | return (MangledName[0] == '8'); | |||
325 | } | |||
326 | ||||
327 | // Remove ext qualifiers since those can appear on either type and are | |||
328 | // therefore not indicative. | |||
329 | MangledName.consumeFront('E'); // 64-bit | |||
330 | MangledName.consumeFront('I'); // restrict | |||
331 | MangledName.consumeFront('F'); // unaligned | |||
332 | ||||
333 | assert(!MangledName.empty())(static_cast <bool> (!MangledName.empty()) ? void (0) : __assert_fail ("!MangledName.empty()", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 333, __extension__ __PRETTY_FUNCTION__)); | |||
334 | ||||
335 | // The next value should be either ABCD (non-member) or QRST (member). | |||
336 | switch (MangledName.front()) { | |||
337 | case 'A': | |||
338 | case 'B': | |||
339 | case 'C': | |||
340 | case 'D': | |||
341 | return false; | |||
342 | case 'Q': | |||
343 | case 'R': | |||
344 | case 'S': | |||
345 | case 'T': | |||
346 | return true; | |||
347 | default: | |||
348 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 348, __extension__ __PRETTY_FUNCTION__)); | |||
349 | } | |||
350 | return false; | |||
351 | } | |||
352 | ||||
353 | static void outputCallingConvention(OutputStream &OS, CallingConv CC) { | |||
354 | outputSpaceIfNecessary(OS); | |||
355 | ||||
356 | switch (CC) { | |||
357 | case CallingConv::Cdecl: | |||
358 | OS << "__cdecl"; | |||
359 | break; | |||
360 | case CallingConv::Fastcall: | |||
361 | OS << "__fastcall"; | |||
362 | break; | |||
363 | case CallingConv::Pascal: | |||
364 | OS << "__pascal"; | |||
365 | break; | |||
366 | case CallingConv::Regcall: | |||
367 | OS << "__regcall"; | |||
368 | break; | |||
369 | case CallingConv::Stdcall: | |||
370 | OS << "__stdcall"; | |||
371 | break; | |||
372 | case CallingConv::Thiscall: | |||
373 | OS << "__thiscall"; | |||
374 | break; | |||
375 | case CallingConv::Eabi: | |||
376 | OS << "__eabi"; | |||
377 | break; | |||
378 | case CallingConv::Vectorcall: | |||
379 | OS << "__vectorcall"; | |||
380 | break; | |||
381 | case CallingConv::Clrcall: | |||
382 | OS << "__clrcall"; | |||
383 | break; | |||
384 | default: | |||
385 | break; | |||
386 | } | |||
387 | } | |||
388 | ||||
389 | // Write a function or template parameter list. | |||
390 | static void outputParameterList(OutputStream &OS, const ParamList &Params) { | |||
391 | if (!Params.Current) { | |||
392 | OS << "void"; | |||
393 | return; | |||
394 | } | |||
395 | ||||
396 | const ParamList *Head = &Params; | |||
397 | while (Head) { | |||
398 | Type::outputPre(OS, *Head->Current); | |||
399 | Type::outputPost(OS, *Head->Current); | |||
400 | ||||
401 | Head = Head->Next; | |||
402 | ||||
403 | if (Head) | |||
404 | OS << ", "; | |||
405 | } | |||
406 | } | |||
407 | ||||
408 | static void outputTemplateParams(OutputStream &OS, const Name &TheName) { | |||
409 | if (!TheName.TemplateParams.Current) | |||
410 | return; | |||
411 | ||||
412 | OS << "<"; | |||
413 | outputParameterList(OS, TheName.TemplateParams); | |||
414 | OS << ">"; | |||
415 | } | |||
416 | ||||
417 | static void outputName(OutputStream &OS, const Name *TheName) { | |||
418 | if (!TheName) | |||
419 | return; | |||
420 | ||||
421 | outputSpaceIfNecessary(OS); | |||
422 | ||||
423 | // Print out namespaces or outer class BackReferences. | |||
424 | for (; TheName->Next; TheName = TheName->Next) { | |||
425 | OS << TheName->Str; | |||
426 | outputTemplateParams(OS, *TheName); | |||
427 | OS << "::"; | |||
428 | } | |||
429 | ||||
430 | // Print out a regular name. | |||
431 | if (TheName->Operator.empty()) { | |||
432 | OS << TheName->Str; | |||
433 | outputTemplateParams(OS, *TheName); | |||
434 | return; | |||
435 | } | |||
436 | ||||
437 | // Print out ctor or dtor. | |||
438 | if (TheName->Operator == "ctor" || TheName->Operator == "dtor") { | |||
439 | OS << TheName->Str; | |||
440 | outputTemplateParams(OS, *TheName); | |||
441 | OS << "::"; | |||
442 | if (TheName->Operator == "dtor") | |||
443 | OS << "~"; | |||
444 | OS << TheName->Str; | |||
445 | outputTemplateParams(OS, *TheName); | |||
446 | return; | |||
447 | } | |||
448 | ||||
449 | // Print out an overloaded operator. | |||
450 | if (!TheName->Str.empty()) | |||
451 | OS << TheName->Str << "::"; | |||
452 | OS << "operator" << TheName->Operator; | |||
453 | } | |||
454 | ||||
455 | namespace { | |||
456 | ||||
457 | Type *Type::clone(ArenaAllocator &Arena) const { | |||
458 | return Arena.alloc<Type>(*this); | |||
459 | } | |||
460 | ||||
461 | // Write the "first half" of a given type. | |||
462 | void Type::outputPre(OutputStream &OS, Type &Ty) { | |||
463 | // Function types require custom handling of const and static so we | |||
464 | // handle them separately. All other types use the same decoration | |||
465 | // for these modifiers, so handle them here in common code. | |||
466 | if (Ty.Prim == PrimTy::Function) { | |||
467 | Ty.outputPre(OS); | |||
468 | return; | |||
469 | } | |||
470 | ||||
471 | switch (Ty.Storage) { | |||
472 | case StorageClass::PrivateStatic: | |||
473 | case StorageClass::PublicStatic: | |||
474 | case StorageClass::ProtectedStatic: | |||
475 | OS << "static "; | |||
476 | default: | |||
477 | break; | |||
478 | } | |||
479 | Ty.outputPre(OS); | |||
480 | ||||
481 | if (Ty.Quals & Q_Const) { | |||
482 | outputSpaceIfNecessary(OS); | |||
483 | OS << "const"; | |||
484 | } | |||
485 | ||||
486 | if (Ty.Quals & Q_Volatile) { | |||
487 | outputSpaceIfNecessary(OS); | |||
488 | OS << "volatile"; | |||
489 | } | |||
490 | ||||
491 | if (Ty.Quals & Q_Restrict) { | |||
492 | outputSpaceIfNecessary(OS); | |||
493 | OS << "__restrict"; | |||
494 | } | |||
495 | } | |||
496 | ||||
497 | // Write the "second half" of a given type. | |||
498 | void Type::outputPost(OutputStream &OS, Type &Ty) { Ty.outputPost(OS); } | |||
499 | ||||
500 | void Type::outputPre(OutputStream &OS) { | |||
501 | switch (Prim) { | |||
502 | case PrimTy::Void: | |||
503 | OS << "void"; | |||
504 | break; | |||
505 | case PrimTy::Bool: | |||
506 | OS << "bool"; | |||
507 | break; | |||
508 | case PrimTy::Char: | |||
509 | OS << "char"; | |||
510 | break; | |||
511 | case PrimTy::Schar: | |||
512 | OS << "signed char"; | |||
513 | break; | |||
514 | case PrimTy::Uchar: | |||
515 | OS << "unsigned char"; | |||
516 | break; | |||
517 | case PrimTy::Short: | |||
518 | OS << "short"; | |||
519 | break; | |||
520 | case PrimTy::Ushort: | |||
521 | OS << "unsigned short"; | |||
522 | break; | |||
523 | case PrimTy::Int: | |||
524 | OS << "int"; | |||
525 | break; | |||
526 | case PrimTy::Uint: | |||
527 | OS << "unsigned int"; | |||
528 | break; | |||
529 | case PrimTy::Long: | |||
530 | OS << "long"; | |||
531 | break; | |||
532 | case PrimTy::Ulong: | |||
533 | OS << "unsigned long"; | |||
534 | break; | |||
535 | case PrimTy::Int64: | |||
536 | OS << "__int64"; | |||
537 | break; | |||
538 | case PrimTy::Uint64: | |||
539 | OS << "unsigned __int64"; | |||
540 | break; | |||
541 | case PrimTy::Wchar: | |||
542 | OS << "wchar_t"; | |||
543 | break; | |||
544 | case PrimTy::Float: | |||
545 | OS << "float"; | |||
546 | break; | |||
547 | case PrimTy::Double: | |||
548 | OS << "double"; | |||
549 | break; | |||
550 | case PrimTy::Ldouble: | |||
551 | OS << "long double"; | |||
552 | break; | |||
553 | default: | |||
554 | assert(false && "Invalid primitive type!")(static_cast <bool> (false && "Invalid primitive type!" ) ? void (0) : __assert_fail ("false && \"Invalid primitive type!\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 554, __extension__ __PRETTY_FUNCTION__)); | |||
555 | } | |||
556 | } | |||
557 | void Type::outputPost(OutputStream &OS) {} | |||
558 | ||||
559 | Type *PointerType::clone(ArenaAllocator &Arena) const { | |||
560 | return Arena.alloc<PointerType>(*this); | |||
561 | } | |||
562 | ||||
563 | static void outputPointerIndicator(OutputStream &OS, PointerAffinity Affinity, | |||
564 | const Name *MemberName, | |||
565 | const Type *Pointee) { | |||
566 | // "[]" and "()" (for function parameters) take precedence over "*", | |||
567 | // so "int *x(int)" means "x is a function returning int *". We need | |||
568 | // parentheses to supercede the default precedence. (e.g. we want to | |||
569 | // emit something like "int (*x)(int)".) | |||
570 | if (Pointee->Prim == PrimTy::Function || Pointee->Prim == PrimTy::Array) { | |||
571 | OS << "("; | |||
572 | if (Pointee->Prim == PrimTy::Function) { | |||
573 | const FunctionType *FTy = static_cast<const FunctionType *>(Pointee); | |||
574 | assert(FTy->IsFunctionPointer)(static_cast <bool> (FTy->IsFunctionPointer) ? void ( 0) : __assert_fail ("FTy->IsFunctionPointer", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 574, __extension__ __PRETTY_FUNCTION__)); | |||
575 | outputCallingConvention(OS, FTy->CallConvention); | |||
576 | OS << " "; | |||
577 | } | |||
578 | } | |||
579 | ||||
580 | if (MemberName) { | |||
581 | outputName(OS, MemberName); | |||
582 | OS << "::"; | |||
583 | } | |||
584 | ||||
585 | if (Affinity == PointerAffinity::Pointer) | |||
586 | OS << "*"; | |||
587 | else | |||
588 | OS << "&"; | |||
589 | } | |||
590 | ||||
591 | void PointerType::outputPre(OutputStream &OS) { | |||
592 | Type::outputPre(OS, *Pointee); | |||
593 | ||||
594 | outputSpaceIfNecessary(OS); | |||
595 | ||||
596 | if (Quals & Q_Unaligned) | |||
597 | OS << "__unaligned "; | |||
598 | ||||
599 | PointerAffinity Affinity = (Prim == PrimTy::Ptr) ? PointerAffinity::Pointer | |||
600 | : PointerAffinity::Reference; | |||
601 | ||||
602 | outputPointerIndicator(OS, Affinity, nullptr, Pointee); | |||
603 | ||||
604 | // FIXME: We should output this, but it requires updating lots of tests. | |||
605 | // if (Ty.Quals & Q_Pointer64) | |||
606 | // OS << " __ptr64"; | |||
607 | } | |||
608 | ||||
609 | void PointerType::outputPost(OutputStream &OS) { | |||
610 | if (Pointee->Prim == PrimTy::Function || Pointee->Prim == PrimTy::Array) | |||
611 | OS << ")"; | |||
612 | ||||
613 | Type::outputPost(OS, *Pointee); | |||
614 | } | |||
615 | ||||
616 | Type *MemberPointerType::clone(ArenaAllocator &Arena) const { | |||
617 | return Arena.alloc<MemberPointerType>(*this); | |||
618 | } | |||
619 | ||||
620 | void MemberPointerType::outputPre(OutputStream &OS) { | |||
621 | Type::outputPre(OS, *Pointee); | |||
622 | ||||
623 | outputSpaceIfNecessary(OS); | |||
624 | ||||
625 | outputPointerIndicator(OS, PointerAffinity::Pointer, MemberName, Pointee); | |||
626 | ||||
627 | // FIXME: We should output this, but it requires updating lots of tests. | |||
628 | // if (Ty.Quals & Q_Pointer64) | |||
629 | // OS << " __ptr64"; | |||
630 | if (Quals & Q_Restrict) | |||
631 | OS << " __restrict"; | |||
632 | } | |||
633 | ||||
634 | void MemberPointerType::outputPost(OutputStream &OS) { | |||
635 | if (Pointee->Prim == PrimTy::Function || Pointee->Prim == PrimTy::Array) | |||
636 | OS << ")"; | |||
637 | ||||
638 | Type::outputPost(OS, *Pointee); | |||
639 | } | |||
640 | ||||
641 | Type *FunctionType::clone(ArenaAllocator &Arena) const { | |||
642 | return Arena.alloc<FunctionType>(*this); | |||
643 | } | |||
644 | ||||
645 | void FunctionType::outputPre(OutputStream &OS) { | |||
646 | if (!(FunctionClass & Global)) { | |||
647 | if (FunctionClass & Static) | |||
648 | OS << "static "; | |||
649 | } | |||
650 | ||||
651 | if (ReturnType) { | |||
652 | Type::outputPre(OS, *ReturnType); | |||
653 | OS << " "; | |||
654 | } | |||
655 | ||||
656 | // Function pointers print the calling convention as void (__cdecl *)(params) | |||
657 | // rather than void __cdecl (*)(params). So we need to let the PointerType | |||
658 | // class handle this. | |||
659 | if (!IsFunctionPointer) | |||
660 | outputCallingConvention(OS, CallConvention); | |||
661 | } | |||
662 | ||||
663 | void FunctionType::outputPost(OutputStream &OS) { | |||
664 | OS << "("; | |||
665 | outputParameterList(OS, Params); | |||
666 | OS << ")"; | |||
667 | if (Quals & Q_Const) | |||
668 | OS << " const"; | |||
669 | if (Quals & Q_Volatile) | |||
670 | OS << " volatile"; | |||
671 | ||||
672 | if (ReturnType) | |||
673 | Type::outputPost(OS, *ReturnType); | |||
674 | return; | |||
675 | } | |||
676 | ||||
677 | Type *UdtType::clone(ArenaAllocator &Arena) const { | |||
678 | return Arena.alloc<UdtType>(*this); | |||
679 | } | |||
680 | ||||
681 | void UdtType::outputPre(OutputStream &OS) { | |||
682 | switch (Prim) { | |||
683 | case PrimTy::Class: | |||
684 | OS << "class "; | |||
685 | break; | |||
686 | case PrimTy::Struct: | |||
687 | OS << "struct "; | |||
688 | break; | |||
689 | case PrimTy::Union: | |||
690 | OS << "union "; | |||
691 | break; | |||
692 | case PrimTy::Enum: | |||
693 | OS << "enum "; | |||
694 | break; | |||
695 | default: | |||
696 | assert(false && "Not a udt type!")(static_cast <bool> (false && "Not a udt type!" ) ? void (0) : __assert_fail ("false && \"Not a udt type!\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 696, __extension__ __PRETTY_FUNCTION__)); | |||
697 | } | |||
698 | ||||
699 | outputName(OS, UdtName); | |||
700 | } | |||
701 | ||||
702 | Type *ArrayType::clone(ArenaAllocator &Arena) const { | |||
703 | return Arena.alloc<ArrayType>(*this); | |||
704 | } | |||
705 | ||||
706 | void ArrayType::outputPre(OutputStream &OS) { | |||
707 | Type::outputPre(OS, *ElementType); | |||
708 | } | |||
709 | ||||
710 | void ArrayType::outputPost(OutputStream &OS) { | |||
711 | if (ArrayDimension > 0) | |||
712 | OS << "[" << ArrayDimension << "]"; | |||
713 | if (NextDimension) | |||
714 | Type::outputPost(OS, *NextDimension); | |||
715 | else if (ElementType) | |||
716 | Type::outputPost(OS, *ElementType); | |||
717 | } | |||
718 | ||||
719 | } // namespace | |||
720 | ||||
721 | namespace { | |||
722 | ||||
723 | // Demangler class takes the main role in demangling symbols. | |||
724 | // It has a set of functions to parse mangled symbols into Type instances. | |||
725 | // It also has a set of functions to cnovert Type instances to strings. | |||
726 | class Demangler { | |||
727 | public: | |||
728 | Demangler(OutputStream &OS, StringView s) : OS(OS), MangledName(s) {} | |||
729 | ||||
730 | // You are supposed to call parse() first and then check if error is true. If | |||
731 | // it is false, call output() to write the formatted name to the given stream. | |||
732 | void parse(); | |||
733 | void output(); | |||
734 | ||||
735 | // True if an error occurred. | |||
736 | bool Error = false; | |||
737 | ||||
738 | private: | |||
739 | Type *demangleVariableEncoding(); | |||
740 | Type *demangleFunctionEncoding(); | |||
741 | ||||
742 | Qualifiers demanglePointerExtQualifiers(); | |||
743 | ||||
744 | // Parser functions. This is a recursive-descent parser. | |||
745 | Type *demangleType(QualifierMangleMode QMM); | |||
746 | Type *demangleBasicType(); | |||
747 | UdtType *demangleClassType(); | |||
748 | PointerType *demanglePointerType(); | |||
749 | MemberPointerType *demangleMemberPointerType(); | |||
750 | FunctionType *demangleFunctionType(bool HasThisQuals, bool IsFunctionPointer); | |||
751 | ||||
752 | ArrayType *demangleArrayType(); | |||
753 | ||||
754 | ParamList demangleTemplateParameterList(); | |||
755 | ParamList demangleFunctionParameterList(); | |||
756 | ||||
757 | int demangleNumber(); | |||
758 | void demangleNamePiece(Name &Node, bool IsHead); | |||
759 | ||||
760 | StringView demangleString(bool memorize); | |||
761 | void memorizeString(StringView s); | |||
762 | Name *demangleName(); | |||
763 | void demangleOperator(Name *); | |||
764 | StringView demangleOperatorName(); | |||
765 | FuncClass demangleFunctionClass(); | |||
766 | CallingConv demangleCallingConvention(); | |||
767 | StorageClass demangleVariableStorageClass(); | |||
768 | ReferenceKind demangleReferenceKind(); | |||
769 | void demangleThrowSpecification(); | |||
770 | ||||
771 | std::pair<Qualifiers, bool> demangleQualifiers(); | |||
772 | ||||
773 | // The result is written to this stream. | |||
774 | OutputStream OS; | |||
775 | ||||
776 | // Mangled symbol. demangle* functions shorten this string | |||
777 | // as they parse it. | |||
778 | StringView MangledName; | |||
779 | ||||
780 | // A parsed mangled symbol. | |||
781 | Type *SymbolType = nullptr; | |||
782 | ||||
783 | // The main symbol name. (e.g. "ns::foo" in "int ns::foo()".) | |||
784 | Name *SymbolName = nullptr; | |||
785 | ||||
786 | // Memory allocator. | |||
787 | ArenaAllocator Arena; | |||
788 | ||||
789 | // A single type uses one global back-ref table for all function params. | |||
790 | // This means back-refs can even go "into" other types. Examples: | |||
791 | // | |||
792 | // // Second int* is a back-ref to first. | |||
793 | // void foo(int *, int*); | |||
794 | // | |||
795 | // // Second int* is not a back-ref to first (first is not a function param). | |||
796 | // int* foo(int*); | |||
797 | // | |||
798 | // // Second int* is a back-ref to first (ALL function types share the same | |||
799 | // // back-ref map. | |||
800 | // using F = void(*)(int*); | |||
801 | // F G(int *); | |||
802 | Type *FunctionParamBackRefs[10]; | |||
803 | size_t FunctionParamBackRefCount = 0; | |||
804 | ||||
805 | // The first 10 BackReferences in a mangled name can be back-referenced by | |||
806 | // special name @[0-9]. This is a storage for the first 10 BackReferences. | |||
807 | StringView BackReferences[10]; | |||
808 | size_t BackRefCount = 0; | |||
809 | }; | |||
810 | } // namespace | |||
811 | ||||
812 | // Parser entry point. | |||
813 | void Demangler::parse() { | |||
814 | // MSVC-style mangled symbols must start with '?'. | |||
815 | if (!MangledName.consumeFront("?")) { | |||
816 | SymbolName = Arena.alloc<Name>(); | |||
817 | SymbolName->Str = MangledName; | |||
818 | SymbolType = Arena.alloc<Type>(); | |||
819 | SymbolType->Prim = PrimTy::Unknown; | |||
820 | } | |||
821 | ||||
822 | // What follows is a main symbol name. This may include | |||
823 | // namespaces or class BackReferences. | |||
824 | SymbolName = demangleName(); | |||
825 | ||||
826 | // Read a variable. | |||
827 | if (startsWithDigit(MangledName)) { | |||
828 | SymbolType = demangleVariableEncoding(); | |||
829 | return; | |||
830 | } | |||
831 | ||||
832 | // Read a function. | |||
833 | SymbolType = demangleFunctionEncoding(); | |||
834 | } | |||
835 | ||||
836 | // <type-encoding> ::= <storage-class> <variable-type> | |||
837 | // <storage-class> ::= 0 # private static member | |||
838 | // ::= 1 # protected static member | |||
839 | // ::= 2 # public static member | |||
840 | // ::= 3 # global | |||
841 | // ::= 4 # static local | |||
842 | ||||
843 | Type *Demangler::demangleVariableEncoding() { | |||
844 | StorageClass SC = demangleVariableStorageClass(); | |||
845 | ||||
846 | Type *Ty = demangleType(QualifierMangleMode::Drop); | |||
847 | ||||
848 | Ty->Storage = SC; | |||
849 | ||||
850 | // <variable-type> ::= <type> <cvr-qualifiers> | |||
851 | // ::= <type> <pointee-cvr-qualifiers> # pointers, references | |||
852 | switch (Ty->Prim) { | |||
853 | case PrimTy::Ptr: | |||
854 | case PrimTy::Ref: | |||
855 | case PrimTy::MemberPtr: { | |||
856 | Qualifiers ExtraChildQuals = Q_None; | |||
857 | Ty->Quals = Qualifiers(Ty->Quals | demanglePointerExtQualifiers()); | |||
858 | ||||
859 | bool IsMember = false; | |||
860 | std::tie(ExtraChildQuals, IsMember) = demangleQualifiers(); | |||
861 | ||||
862 | if (Ty->Prim == PrimTy::MemberPtr) { | |||
863 | assert(IsMember)(static_cast <bool> (IsMember) ? void (0) : __assert_fail ("IsMember", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 863, __extension__ __PRETTY_FUNCTION__)); | |||
864 | Name *BackRefName = demangleName(); | |||
865 | (void)BackRefName; | |||
866 | MemberPointerType *MPTy = static_cast<MemberPointerType *>(Ty); | |||
867 | MPTy->Pointee->Quals = Qualifiers(MPTy->Pointee->Quals | ExtraChildQuals); | |||
868 | } else { | |||
869 | PointerType *PTy = static_cast<PointerType *>(Ty); | |||
870 | PTy->Pointee->Quals = Qualifiers(PTy->Pointee->Quals | ExtraChildQuals); | |||
871 | } | |||
872 | ||||
873 | break; | |||
874 | } | |||
875 | default: | |||
876 | Ty->Quals = demangleQualifiers().first; | |||
877 | break; | |||
878 | } | |||
879 | ||||
880 | return Ty; | |||
881 | } | |||
882 | ||||
883 | // Sometimes numbers are encoded in mangled symbols. For example, | |||
884 | // "int (*x)[20]" is a valid C type (x is a pointer to an array of | |||
885 | // length 20), so we need some way to embed numbers as part of symbols. | |||
886 | // This function parses it. | |||
887 | // | |||
888 | // <number> ::= [?] <non-negative integer> | |||
889 | // | |||
890 | // <non-negative integer> ::= <decimal digit> # when 1 <= Number <= 10 | |||
891 | // ::= <hex digit>+ @ # when Numbrer == 0 or >= 10 | |||
892 | // | |||
893 | // <hex-digit> ::= [A-P] # A = 0, B = 1, ... | |||
894 | int Demangler::demangleNumber() { | |||
895 | bool neg = MangledName.consumeFront("?"); | |||
896 | ||||
897 | if (startsWithDigit(MangledName)) { | |||
898 | int32_t Ret = MangledName[0] - '0' + 1; | |||
899 | MangledName = MangledName.dropFront(1); | |||
900 | return neg ? -Ret : Ret; | |||
901 | } | |||
902 | ||||
903 | int Ret = 0; | |||
904 | for (size_t i = 0; i < MangledName.size(); ++i) { | |||
905 | char C = MangledName[i]; | |||
906 | if (C == '@') { | |||
907 | MangledName = MangledName.dropFront(i + 1); | |||
908 | return neg ? -Ret : Ret; | |||
909 | } | |||
910 | if ('A' <= C && C <= 'P') { | |||
911 | Ret = (Ret << 4) + (C - 'A'); | |||
912 | continue; | |||
913 | } | |||
914 | break; | |||
915 | } | |||
916 | ||||
917 | Error = true; | |||
918 | return 0; | |||
919 | } | |||
920 | ||||
921 | // Read until the next '@'. | |||
922 | StringView Demangler::demangleString(bool Memorize) { | |||
923 | for (size_t i = 0; i < MangledName.size(); ++i) { | |||
924 | if (MangledName[i] != '@') | |||
925 | continue; | |||
926 | StringView ret = MangledName.substr(0, i); | |||
927 | MangledName = MangledName.dropFront(i + 1); | |||
928 | ||||
929 | if (Memorize) | |||
930 | memorizeString(ret); | |||
931 | return ret; | |||
932 | } | |||
933 | ||||
934 | Error = true; | |||
935 | return ""; | |||
936 | } | |||
937 | ||||
938 | // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9. | |||
939 | // Memorize it. | |||
940 | void Demangler::memorizeString(StringView S) { | |||
941 | if (BackRefCount >= sizeof(BackReferences) / sizeof(*BackReferences)) | |||
942 | return; | |||
943 | for (size_t i = 0; i < BackRefCount; ++i) | |||
944 | if (S == BackReferences[i]) | |||
945 | return; | |||
946 | BackReferences[BackRefCount++] = S; | |||
947 | } | |||
948 | ||||
949 | void Demangler::demangleNamePiece(Name &Node, bool IsHead) { | |||
950 | if (startsWithDigit(MangledName)) { | |||
951 | size_t I = MangledName[0] - '0'; | |||
952 | if (I >= BackRefCount) { | |||
953 | Error = true; | |||
954 | return; | |||
955 | } | |||
956 | MangledName = MangledName.dropFront(); | |||
957 | Node.Str = BackReferences[I]; | |||
958 | } else if (MangledName.consumeFront("?$")) { | |||
959 | // Class template. | |||
960 | Node.Str = demangleString(false); | |||
961 | Node.TemplateParams = demangleTemplateParameterList(); | |||
962 | } else if (!IsHead && MangledName.consumeFront("?A")) { | |||
963 | // Anonymous namespace starts with ?A. So does overloaded operator[], | |||
964 | // but the distinguishing factor is that namespace themselves are not | |||
965 | // mangled, only the variables and functions inside of them are. So | |||
966 | // an anonymous namespace will never occur as the first item in the | |||
967 | // name. | |||
968 | Node.Str = "`anonymous namespace'"; | |||
969 | if (!MangledName.consumeFront('@')) { | |||
970 | Error = true; | |||
971 | return; | |||
972 | } | |||
973 | } else if (MangledName.consumeFront("?")) { | |||
974 | // Overloaded operator. | |||
975 | demangleOperator(&Node); | |||
976 | } else { | |||
977 | // Non-template functions or classes. | |||
978 | Node.Str = demangleString(true); | |||
979 | } | |||
980 | } | |||
981 | ||||
982 | // Parses a name in the form of A@B@C@@ which represents C::B::A. | |||
983 | Name *Demangler::demangleName() { | |||
984 | Name *Head = nullptr; | |||
985 | ||||
986 | while (!MangledName.consumeFront("@")) { | |||
987 | Name *Elem = Arena.alloc<Name>(); | |||
988 | ||||
989 | assert(!Error)(static_cast <bool> (!Error) ? void (0) : __assert_fail ("!Error", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 989, __extension__ __PRETTY_FUNCTION__)); | |||
990 | demangleNamePiece(*Elem, Head == nullptr); | |||
991 | if (Error) | |||
992 | return nullptr; | |||
993 | ||||
994 | Elem->Next = Head; | |||
995 | Head = Elem; | |||
996 | if (MangledName.empty()) { | |||
997 | Error = true; | |||
998 | return nullptr; | |||
999 | } | |||
1000 | } | |||
1001 | ||||
1002 | return Head; | |||
1003 | } | |||
1004 | ||||
1005 | void Demangler::demangleOperator(Name *OpName) { | |||
1006 | OpName->Operator = demangleOperatorName(); | |||
1007 | if (!Error && !MangledName.empty() && MangledName.front() != '@') | |||
1008 | demangleNamePiece(*OpName, false); | |||
1009 | } | |||
1010 | ||||
1011 | StringView Demangler::demangleOperatorName() { | |||
1012 | SwapAndRestore<StringView> RestoreOnError(MangledName, MangledName); | |||
1013 | RestoreOnError.shouldRestore(false); | |||
1014 | ||||
1015 | switch (MangledName.popFront()) { | |||
1016 | case '0': | |||
1017 | return "ctor"; | |||
1018 | case '1': | |||
1019 | return "dtor"; | |||
1020 | case '2': | |||
1021 | return " new"; | |||
1022 | case '3': | |||
1023 | return " delete"; | |||
1024 | case '4': | |||
1025 | return "="; | |||
1026 | case '5': | |||
1027 | return ">>"; | |||
1028 | case '6': | |||
1029 | return "<<"; | |||
1030 | case '7': | |||
1031 | return "!"; | |||
1032 | case '8': | |||
1033 | return "=="; | |||
1034 | case '9': | |||
1035 | return "!="; | |||
1036 | case 'A': | |||
1037 | return "[]"; | |||
1038 | case 'C': | |||
1039 | return "->"; | |||
1040 | case 'D': | |||
1041 | return "*"; | |||
1042 | case 'E': | |||
1043 | return "++"; | |||
1044 | case 'F': | |||
1045 | return "--"; | |||
1046 | case 'G': | |||
1047 | return "-"; | |||
1048 | case 'H': | |||
1049 | return "+"; | |||
1050 | case 'I': | |||
1051 | return "&"; | |||
1052 | case 'J': | |||
1053 | return "->*"; | |||
1054 | case 'K': | |||
1055 | return "/"; | |||
1056 | case 'L': | |||
1057 | return "%"; | |||
1058 | case 'M': | |||
1059 | return "<"; | |||
1060 | case 'N': | |||
1061 | return "<="; | |||
1062 | case 'O': | |||
1063 | return ">"; | |||
1064 | case 'P': | |||
1065 | return ">="; | |||
1066 | case 'Q': | |||
1067 | return ","; | |||
1068 | case 'R': | |||
1069 | return "()"; | |||
1070 | case 'S': | |||
1071 | return "~"; | |||
1072 | case 'T': | |||
1073 | return "^"; | |||
1074 | case 'U': | |||
1075 | return "|"; | |||
1076 | case 'V': | |||
1077 | return "&&"; | |||
1078 | case 'W': | |||
1079 | return "||"; | |||
1080 | case 'X': | |||
1081 | return "*="; | |||
1082 | case 'Y': | |||
1083 | return "+="; | |||
1084 | case 'Z': | |||
1085 | return "-="; | |||
1086 | case '_': { | |||
1087 | if (MangledName.empty()) | |||
1088 | break; | |||
1089 | ||||
1090 | switch (MangledName.popFront()) { | |||
1091 | case '0': | |||
1092 | return "/="; | |||
1093 | case '1': | |||
1094 | return "%="; | |||
1095 | case '2': | |||
1096 | return ">>="; | |||
1097 | case '3': | |||
1098 | return "<<="; | |||
1099 | case '4': | |||
1100 | return "&="; | |||
1101 | case '5': | |||
1102 | return "|="; | |||
1103 | case '6': | |||
1104 | return "^="; | |||
1105 | case 'U': | |||
1106 | return " new[]"; | |||
1107 | case 'V': | |||
1108 | return " delete[]"; | |||
1109 | case '_': | |||
1110 | if (MangledName.consumeFront("L")) | |||
1111 | return " co_await"; | |||
1112 | } | |||
1113 | } | |||
1114 | } | |||
1115 | ||||
1116 | Error = true; | |||
1117 | RestoreOnError.shouldRestore(true); | |||
1118 | return ""; | |||
1119 | } | |||
1120 | ||||
1121 | FuncClass Demangler::demangleFunctionClass() { | |||
1122 | SwapAndRestore<StringView> RestoreOnError(MangledName, MangledName); | |||
1123 | RestoreOnError.shouldRestore(false); | |||
1124 | ||||
1125 | switch (MangledName.popFront()) { | |||
1126 | case 'A': | |||
1127 | return Private; | |||
1128 | case 'B': | |||
1129 | return FuncClass(Private | Far); | |||
1130 | case 'C': | |||
1131 | return FuncClass(Private | Static); | |||
1132 | case 'D': | |||
1133 | return FuncClass(Private | Static); | |||
1134 | case 'E': | |||
1135 | return FuncClass(Private | Virtual); | |||
1136 | case 'F': | |||
1137 | return FuncClass(Private | Virtual); | |||
1138 | case 'I': | |||
1139 | return Protected; | |||
1140 | case 'J': | |||
1141 | return FuncClass(Protected | Far); | |||
1142 | case 'K': | |||
1143 | return FuncClass(Protected | Static); | |||
1144 | case 'L': | |||
1145 | return FuncClass(Protected | Static | Far); | |||
1146 | case 'M': | |||
1147 | return FuncClass(Protected | Virtual); | |||
1148 | case 'N': | |||
1149 | return FuncClass(Protected | Virtual | Far); | |||
1150 | case 'Q': | |||
1151 | return Public; | |||
1152 | case 'R': | |||
1153 | return FuncClass(Public | Far); | |||
1154 | case 'S': | |||
1155 | return FuncClass(Public | Static); | |||
1156 | case 'T': | |||
1157 | return FuncClass(Public | Static | Far); | |||
1158 | case 'U': | |||
1159 | return FuncClass(Public | Virtual); | |||
1160 | case 'V': | |||
1161 | return FuncClass(Public | Virtual | Far); | |||
1162 | case 'Y': | |||
1163 | return Global; | |||
1164 | case 'Z': | |||
1165 | return FuncClass(Global | Far); | |||
1166 | } | |||
1167 | ||||
1168 | Error = true; | |||
1169 | RestoreOnError.shouldRestore(true); | |||
1170 | return Public; | |||
1171 | } | |||
1172 | ||||
1173 | CallingConv Demangler::demangleCallingConvention() { | |||
1174 | switch (MangledName.popFront()) { | |||
1175 | case 'A': | |||
1176 | case 'B': | |||
1177 | return CallingConv::Cdecl; | |||
1178 | case 'C': | |||
1179 | case 'D': | |||
1180 | return CallingConv::Pascal; | |||
1181 | case 'E': | |||
1182 | case 'F': | |||
1183 | return CallingConv::Thiscall; | |||
1184 | case 'G': | |||
1185 | case 'H': | |||
1186 | return CallingConv::Stdcall; | |||
1187 | case 'I': | |||
1188 | case 'J': | |||
1189 | return CallingConv::Fastcall; | |||
1190 | case 'M': | |||
1191 | case 'N': | |||
1192 | return CallingConv::Clrcall; | |||
1193 | case 'O': | |||
1194 | case 'P': | |||
1195 | return CallingConv::Eabi; | |||
1196 | case 'Q': | |||
1197 | return CallingConv::Vectorcall; | |||
1198 | } | |||
1199 | ||||
1200 | return CallingConv::None; | |||
1201 | } | |||
1202 | ||||
1203 | StorageClass Demangler::demangleVariableStorageClass() { | |||
1204 | assert(std::isdigit(MangledName.front()))(static_cast <bool> (std::isdigit(MangledName.front())) ? void (0) : __assert_fail ("std::isdigit(MangledName.front())" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 1204, __extension__ __PRETTY_FUNCTION__)); | |||
1205 | ||||
1206 | switch (MangledName.popFront()) { | |||
1207 | case '0': | |||
1208 | return StorageClass::PrivateStatic; | |||
1209 | case '1': | |||
1210 | return StorageClass::ProtectedStatic; | |||
1211 | case '2': | |||
1212 | return StorageClass::PublicStatic; | |||
1213 | case '3': | |||
1214 | return StorageClass::Global; | |||
1215 | case '4': | |||
1216 | return StorageClass::FunctionLocalStatic; | |||
1217 | } | |||
1218 | Error = true; | |||
1219 | return StorageClass::None; | |||
1220 | } | |||
1221 | ||||
1222 | std::pair<Qualifiers, bool> Demangler::demangleQualifiers() { | |||
1223 | ||||
1224 | switch (MangledName.popFront()) { | |||
1225 | // Member qualifiers | |||
1226 | case 'Q': | |||
1227 | return std::make_pair(Q_None, true); | |||
1228 | case 'R': | |||
1229 | return std::make_pair(Q_Const, true); | |||
1230 | case 'S': | |||
1231 | return std::make_pair(Q_Volatile, true); | |||
1232 | case 'T': | |||
1233 | return std::make_pair(Qualifiers(Q_Const | Q_Volatile), true); | |||
1234 | // Non-Member qualifiers | |||
1235 | case 'A': | |||
1236 | return std::make_pair(Q_None, false); | |||
1237 | case 'B': | |||
1238 | return std::make_pair(Q_Const, false); | |||
1239 | case 'C': | |||
1240 | return std::make_pair(Q_Volatile, false); | |||
1241 | case 'D': | |||
1242 | return std::make_pair(Qualifiers(Q_Const | Q_Volatile), false); | |||
1243 | } | |||
1244 | Error = true; | |||
1245 | return std::make_pair(Q_None, false); | |||
1246 | } | |||
1247 | ||||
1248 | // <variable-type> ::= <type> <cvr-qualifiers> | |||
1249 | // ::= <type> <pointee-cvr-qualifiers> # pointers, references | |||
1250 | Type *Demangler::demangleType(QualifierMangleMode QMM) { | |||
1251 | Qualifiers Quals = Q_None; | |||
1252 | bool IsMember = false; | |||
1253 | bool IsMemberKnown = false; | |||
1254 | if (QMM == QualifierMangleMode::Mangle) { | |||
1255 | std::tie(Quals, IsMember) = demangleQualifiers(); | |||
1256 | IsMemberKnown = true; | |||
1257 | } else if (QMM == QualifierMangleMode::Result) { | |||
1258 | if (MangledName.consumeFront('?')) { | |||
1259 | std::tie(Quals, IsMember) = demangleQualifiers(); | |||
1260 | IsMemberKnown = true; | |||
1261 | } | |||
1262 | } | |||
1263 | ||||
1264 | Type *Ty = nullptr; | |||
1265 | switch (MangledName.front()) { | |||
1266 | case 'T': // union | |||
1267 | case 'U': // struct | |||
1268 | case 'V': // class | |||
1269 | case 'W': // enum | |||
1270 | Ty = demangleClassType(); | |||
1271 | break; | |||
1272 | case 'A': // foo & | |||
1273 | case 'P': // foo * | |||
1274 | case 'Q': // foo *const | |||
1275 | case 'R': // foo *volatile | |||
1276 | case 'S': // foo *const volatile | |||
1277 | if (!IsMemberKnown) | |||
1278 | IsMember = isMemberPointer(MangledName); | |||
1279 | if (IsMember) | |||
1280 | Ty = demangleMemberPointerType(); | |||
1281 | else | |||
1282 | Ty = demanglePointerType(); | |||
1283 | break; | |||
1284 | case 'Y': | |||
1285 | Ty = demangleArrayType(); | |||
1286 | break; | |||
1287 | default: | |||
1288 | Ty = demangleBasicType(); | |||
1289 | break; | |||
1290 | } | |||
1291 | Ty->Quals = Qualifiers(Ty->Quals | Quals); | |||
1292 | return Ty; | |||
1293 | } | |||
1294 | ||||
1295 | ReferenceKind Demangler::demangleReferenceKind() { | |||
1296 | if (MangledName.consumeFront('G')) | |||
1297 | return ReferenceKind::LValueRef; | |||
1298 | else if (MangledName.consumeFront('H')) | |||
1299 | return ReferenceKind::RValueRef; | |||
1300 | return ReferenceKind::None; | |||
1301 | } | |||
1302 | ||||
1303 | void Demangler::demangleThrowSpecification() { | |||
1304 | if (MangledName.consumeFront('Z')) | |||
1305 | return; | |||
1306 | ||||
1307 | Error = true; | |||
1308 | } | |||
1309 | ||||
1310 | FunctionType *Demangler::demangleFunctionType(bool HasThisQuals, | |||
1311 | bool IsFunctionPointer) { | |||
1312 | FunctionType *FTy = Arena.alloc<FunctionType>(); | |||
1313 | FTy->Prim = PrimTy::Function; | |||
1314 | FTy->IsFunctionPointer = IsFunctionPointer; | |||
1315 | ||||
1316 | if (HasThisQuals) { | |||
1317 | FTy->Quals = demanglePointerExtQualifiers(); | |||
1318 | FTy->RefKind = demangleReferenceKind(); | |||
1319 | FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers().first); | |||
1320 | } | |||
1321 | ||||
1322 | // Fields that appear on both member and non-member functions. | |||
1323 | FTy->CallConvention = demangleCallingConvention(); | |||
1324 | ||||
1325 | // <return-type> ::= <type> | |||
1326 | // ::= @ # structors (they have no declared return type) | |||
1327 | bool IsStructor = MangledName.consumeFront('@'); | |||
1328 | if (!IsStructor) | |||
1329 | FTy->ReturnType = demangleType(QualifierMangleMode::Result); | |||
1330 | ||||
1331 | FTy->Params = demangleFunctionParameterList(); | |||
1332 | ||||
1333 | demangleThrowSpecification(); | |||
1334 | ||||
1335 | return FTy; | |||
1336 | } | |||
1337 | ||||
1338 | Type *Demangler::demangleFunctionEncoding() { | |||
1339 | FuncClass FC = demangleFunctionClass(); | |||
1340 | ||||
1341 | bool HasThisQuals = !(FC & (Global | Static)); | |||
1342 | FunctionType *FTy = demangleFunctionType(HasThisQuals, false); | |||
1343 | FTy->FunctionClass = FC; | |||
1344 | ||||
1345 | return FTy; | |||
1346 | } | |||
1347 | ||||
1348 | // Reads a primitive type. | |||
1349 | Type *Demangler::demangleBasicType() { | |||
1350 | Type *Ty = Arena.alloc<Type>(); | |||
1351 | ||||
1352 | switch (MangledName.popFront()) { | |||
1353 | case 'X': | |||
1354 | Ty->Prim = PrimTy::Void; | |||
1355 | break; | |||
1356 | case 'D': | |||
1357 | Ty->Prim = PrimTy::Char; | |||
1358 | break; | |||
1359 | case 'C': | |||
1360 | Ty->Prim = PrimTy::Schar; | |||
1361 | break; | |||
1362 | case 'E': | |||
1363 | Ty->Prim = PrimTy::Uchar; | |||
1364 | break; | |||
1365 | case 'F': | |||
1366 | Ty->Prim = PrimTy::Short; | |||
1367 | break; | |||
1368 | case 'G': | |||
1369 | Ty->Prim = PrimTy::Ushort; | |||
1370 | break; | |||
1371 | case 'H': | |||
1372 | Ty->Prim = PrimTy::Int; | |||
1373 | break; | |||
1374 | case 'I': | |||
1375 | Ty->Prim = PrimTy::Uint; | |||
1376 | break; | |||
1377 | case 'J': | |||
1378 | Ty->Prim = PrimTy::Long; | |||
1379 | break; | |||
1380 | case 'K': | |||
1381 | Ty->Prim = PrimTy::Ulong; | |||
1382 | break; | |||
1383 | case 'M': | |||
1384 | Ty->Prim = PrimTy::Float; | |||
1385 | break; | |||
1386 | case 'N': | |||
1387 | Ty->Prim = PrimTy::Double; | |||
1388 | break; | |||
1389 | case 'O': | |||
1390 | Ty->Prim = PrimTy::Ldouble; | |||
1391 | break; | |||
1392 | case '_': { | |||
1393 | if (MangledName.empty()) { | |||
1394 | Error = true; | |||
1395 | return nullptr; | |||
1396 | } | |||
1397 | switch (MangledName.popFront()) { | |||
1398 | case 'N': | |||
1399 | Ty->Prim = PrimTy::Bool; | |||
1400 | break; | |||
1401 | case 'J': | |||
1402 | Ty->Prim = PrimTy::Int64; | |||
1403 | break; | |||
1404 | case 'K': | |||
1405 | Ty->Prim = PrimTy::Uint64; | |||
1406 | break; | |||
1407 | case 'W': | |||
1408 | Ty->Prim = PrimTy::Wchar; | |||
1409 | break; | |||
1410 | default: | |||
1411 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 1411, __extension__ __PRETTY_FUNCTION__)); | |||
1412 | } | |||
1413 | break; | |||
1414 | } | |||
1415 | } | |||
1416 | return Ty; | |||
1417 | } | |||
1418 | ||||
1419 | UdtType *Demangler::demangleClassType() { | |||
1420 | UdtType *UTy = Arena.alloc<UdtType>(); | |||
1421 | ||||
1422 | switch (MangledName.popFront()) { | |||
1423 | case 'T': | |||
1424 | UTy->Prim = PrimTy::Union; | |||
1425 | break; | |||
1426 | case 'U': | |||
1427 | UTy->Prim = PrimTy::Struct; | |||
1428 | break; | |||
1429 | case 'V': | |||
1430 | UTy->Prim = PrimTy::Class; | |||
1431 | break; | |||
1432 | case 'W': | |||
1433 | if (MangledName.popFront() != '4') { | |||
1434 | Error = true; | |||
1435 | return nullptr; | |||
1436 | } | |||
1437 | UTy->Prim = PrimTy::Enum; | |||
1438 | break; | |||
1439 | default: | |||
1440 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 1440, __extension__ __PRETTY_FUNCTION__)); | |||
1441 | } | |||
1442 | ||||
1443 | UTy->UdtName = demangleName(); | |||
1444 | return UTy; | |||
1445 | } | |||
1446 | ||||
1447 | static std::pair<Qualifiers, PointerAffinity> | |||
1448 | demanglePointerCVQualifiers(StringView &MangledName) { | |||
1449 | switch (MangledName.popFront()) { | |||
1450 | case 'A': | |||
1451 | return std::make_pair(Q_None, PointerAffinity::Reference); | |||
1452 | case 'P': | |||
1453 | return std::make_pair(Q_None, PointerAffinity::Pointer); | |||
1454 | case 'Q': | |||
1455 | return std::make_pair(Q_Const, PointerAffinity::Pointer); | |||
1456 | case 'R': | |||
1457 | return std::make_pair(Q_Volatile, PointerAffinity::Pointer); | |||
1458 | case 'S': | |||
1459 | return std::make_pair(Qualifiers(Q_Const | Q_Volatile), | |||
1460 | PointerAffinity::Pointer); | |||
1461 | default: | |||
1462 | assert(false && "Ty is not a pointer type!")(static_cast <bool> (false && "Ty is not a pointer type!" ) ? void (0) : __assert_fail ("false && \"Ty is not a pointer type!\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 1462, __extension__ __PRETTY_FUNCTION__)); | |||
1463 | } | |||
1464 | return std::make_pair(Q_None, PointerAffinity::Pointer); | |||
1465 | } | |||
1466 | ||||
1467 | // <pointer-type> ::= E? <pointer-cvr-qualifiers> <ext-qualifiers> <type> | |||
1468 | // # the E is required for 64-bit non-static pointers | |||
1469 | PointerType *Demangler::demanglePointerType() { | |||
1470 | PointerType *Pointer = Arena.alloc<PointerType>(); | |||
1471 | ||||
1472 | PointerAffinity Affinity; | |||
1473 | std::tie(Pointer->Quals, Affinity) = demanglePointerCVQualifiers(MangledName); | |||
1474 | ||||
1475 | Pointer->Prim = | |||
1476 | (Affinity == PointerAffinity::Pointer) ? PrimTy::Ptr : PrimTy::Ref; | |||
1477 | if (MangledName.consumeFront("6")) { | |||
1478 | Pointer->Pointee = demangleFunctionType(false, true); | |||
1479 | return Pointer; | |||
1480 | } | |||
1481 | ||||
1482 | Qualifiers ExtQuals = demanglePointerExtQualifiers(); | |||
1483 | Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); | |||
1484 | ||||
1485 | Pointer->Pointee = demangleType(QualifierMangleMode::Mangle); | |||
1486 | return Pointer; | |||
1487 | } | |||
1488 | ||||
1489 | MemberPointerType *Demangler::demangleMemberPointerType() { | |||
1490 | MemberPointerType *Pointer = Arena.alloc<MemberPointerType>(); | |||
1491 | Pointer->Prim = PrimTy::MemberPtr; | |||
1492 | ||||
1493 | PointerAffinity Affinity; | |||
1494 | std::tie(Pointer->Quals, Affinity) = demanglePointerCVQualifiers(MangledName); | |||
1495 | assert(Affinity == PointerAffinity::Pointer)(static_cast <bool> (Affinity == PointerAffinity::Pointer ) ? void (0) : __assert_fail ("Affinity == PointerAffinity::Pointer" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 1495, __extension__ __PRETTY_FUNCTION__)); | |||
1496 | ||||
1497 | Qualifiers ExtQuals = demanglePointerExtQualifiers(); | |||
1498 | Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); | |||
1499 | ||||
1500 | if (MangledName.consumeFront("8")) { | |||
1501 | Pointer->MemberName = demangleName(); | |||
1502 | Pointer->Pointee = demangleFunctionType(true, true); | |||
1503 | } else { | |||
1504 | Qualifiers PointeeQuals = Q_None; | |||
1505 | bool IsMember = false; | |||
1506 | std::tie(PointeeQuals, IsMember) = demangleQualifiers(); | |||
1507 | assert(IsMember)(static_cast <bool> (IsMember) ? void (0) : __assert_fail ("IsMember", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 1507, __extension__ __PRETTY_FUNCTION__)); | |||
1508 | Pointer->MemberName = demangleName(); | |||
1509 | ||||
1510 | Pointer->Pointee = demangleType(QualifierMangleMode::Drop); | |||
1511 | Pointer->Pointee->Quals = PointeeQuals; | |||
1512 | } | |||
1513 | ||||
1514 | return Pointer; | |||
1515 | } | |||
1516 | ||||
1517 | Qualifiers Demangler::demanglePointerExtQualifiers() { | |||
1518 | Qualifiers Quals = Q_None; | |||
1519 | if (MangledName.consumeFront('E')) | |||
1520 | Quals = Qualifiers(Quals | Q_Pointer64); | |||
1521 | if (MangledName.consumeFront('I')) | |||
1522 | Quals = Qualifiers(Quals | Q_Restrict); | |||
1523 | if (MangledName.consumeFront('F')) | |||
1524 | Quals = Qualifiers(Quals | Q_Unaligned); | |||
1525 | ||||
1526 | return Quals; | |||
1527 | } | |||
1528 | ||||
1529 | ArrayType *Demangler::demangleArrayType() { | |||
1530 | assert(MangledName.front() == 'Y')(static_cast <bool> (MangledName.front() == 'Y') ? void (0) : __assert_fail ("MangledName.front() == 'Y'", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 1530, __extension__ __PRETTY_FUNCTION__)); | |||
1531 | MangledName.popFront(); | |||
1532 | ||||
1533 | int Dimension = demangleNumber(); | |||
1534 | if (Dimension <= 0) { | |||
1535 | Error = true; | |||
1536 | return nullptr; | |||
1537 | } | |||
1538 | ||||
1539 | ArrayType *ATy = Arena.alloc<ArrayType>(); | |||
1540 | ArrayType *Dim = ATy; | |||
1541 | for (int I = 0; I < Dimension; ++I) { | |||
1542 | Dim->Prim = PrimTy::Array; | |||
1543 | Dim->ArrayDimension = demangleNumber(); | |||
1544 | Dim->NextDimension = Arena.alloc<ArrayType>(); | |||
1545 | Dim = Dim->NextDimension; | |||
1546 | } | |||
1547 | ||||
1548 | if (MangledName.consumeFront("$$C")) { | |||
1549 | if (MangledName.consumeFront("B")) | |||
1550 | ATy->Quals = Q_Const; | |||
1551 | else if (MangledName.consumeFront("C") || MangledName.consumeFront("D")) | |||
1552 | ATy->Quals = Qualifiers(Q_Const | Q_Volatile); | |||
1553 | else if (!MangledName.consumeFront("A")) | |||
1554 | Error = true; | |||
1555 | } | |||
1556 | ||||
1557 | ATy->ElementType = demangleType(QualifierMangleMode::Drop); | |||
1558 | Dim->ElementType = ATy->ElementType; | |||
1559 | return ATy; | |||
1560 | } | |||
1561 | ||||
1562 | // Reads a function or a template parameters. | |||
1563 | ParamList Demangler::demangleFunctionParameterList() { | |||
1564 | // Empty parameter list. | |||
1565 | if (MangledName.consumeFront('X')) | |||
1566 | return {}; | |||
1567 | ||||
1568 | ParamList *Head; | |||
1569 | ParamList **Current = &Head; | |||
1570 | while (!Error && !MangledName.startsWith('@') && | |||
1571 | !MangledName.startsWith('Z')) { | |||
1572 | ||||
1573 | if (startsWithDigit(MangledName)) { | |||
1574 | size_t N = MangledName[0] - '0'; | |||
1575 | if (N >= FunctionParamBackRefCount) { | |||
1576 | Error = true; | |||
1577 | return {}; | |||
1578 | } | |||
1579 | MangledName = MangledName.dropFront(); | |||
1580 | ||||
1581 | *Current = Arena.alloc<ParamList>(); | |||
1582 | (*Current)->Current = FunctionParamBackRefs[N]->clone(Arena); | |||
1583 | Current = &(*Current)->Next; | |||
1584 | continue; | |||
1585 | } | |||
1586 | ||||
1587 | size_t OldSize = MangledName.size(); | |||
1588 | ||||
1589 | *Current = Arena.alloc<ParamList>(); | |||
1590 | (*Current)->Current = demangleType(QualifierMangleMode::Drop); | |||
1591 | ||||
1592 | size_t CharsConsumed = OldSize - MangledName.size(); | |||
1593 | assert(CharsConsumed != 0)(static_cast <bool> (CharsConsumed != 0) ? void (0) : __assert_fail ("CharsConsumed != 0", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Demangle/MicrosoftDemangle.cpp" , 1593, __extension__ __PRETTY_FUNCTION__)); | |||
1594 | ||||
1595 | // Single-letter types are ignored for backreferences because memorizing | |||
1596 | // them doesn't save anything. | |||
1597 | if (FunctionParamBackRefCount <= 9 && CharsConsumed > 1) | |||
1598 | FunctionParamBackRefs[FunctionParamBackRefCount++] = (*Current)->Current; | |||
1599 | ||||
1600 | Current = &(*Current)->Next; | |||
1601 | } | |||
1602 | ||||
1603 | if (Error) | |||
1604 | return {}; | |||
1605 | ||||
1606 | // A non-empty parameter list is terminated by either 'Z' (variadic) parameter | |||
1607 | // list or '@' (non variadic). Careful not to consume "@Z", as in that case | |||
1608 | // the following Z could be a throw specifier. | |||
1609 | if (MangledName.consumeFront('@')) | |||
1610 | return *Head; | |||
1611 | ||||
1612 | if (MangledName.consumeFront('Z')) { | |||
1613 | Head->IsVariadic = true; | |||
| ||||
1614 | return *Head; | |||
1615 | } | |||
1616 | ||||
1617 | Error = true; | |||
1618 | return {}; | |||
1619 | } | |||
1620 | ||||
1621 | ParamList Demangler::demangleTemplateParameterList() { | |||
1622 | ParamList *Head; | |||
1623 | ParamList **Current = &Head; | |||
1624 | while (!Error && !MangledName.startsWith('@')) { | |||
1625 | ||||
1626 | // Template parameter lists don't participate in back-referencing. | |||
1627 | *Current = Arena.alloc<ParamList>(); | |||
1628 | (*Current)->Current = demangleType(QualifierMangleMode::Drop); | |||
1629 | ||||
1630 | Current = &(*Current)->Next; | |||
1631 | } | |||
1632 | ||||
1633 | if (Error) | |||
1634 | return {}; | |||
1635 | ||||
1636 | // Template parameter lists cannot be variadic, so it can only be terminated | |||
1637 | // by @. | |||
1638 | if (MangledName.consumeFront('@')) | |||
1639 | return *Head; | |||
1640 | Error = true; | |||
1641 | return {}; | |||
1642 | } | |||
1643 | ||||
1644 | void Demangler::output() { | |||
1645 | // Converts an AST to a string. | |||
1646 | // | |||
1647 | // Converting an AST representing a C++ type to a string is tricky due | |||
1648 | // to the bad grammar of the C++ declaration inherited from C. You have | |||
1649 | // to construct a string from inside to outside. For example, if a type | |||
1650 | // X is a pointer to a function returning int, the order you create a | |||
1651 | // string becomes something like this: | |||
1652 | // | |||
1653 | // (1) X is a pointer: *X | |||
1654 | // (2) (1) is a function returning int: int (*X)() | |||
1655 | // | |||
1656 | // So you cannot construct a result just by appending strings to a result. | |||
1657 | // | |||
1658 | // To deal with this, we split the function into two. outputPre() writes | |||
1659 | // the "first half" of type declaration, and outputPost() writes the | |||
1660 | // "second half". For example, outputPre() writes a return type for a | |||
1661 | // function and outputPost() writes an parameter list. | |||
1662 | Type::outputPre(OS, *SymbolType); | |||
1663 | outputName(OS, SymbolName); | |||
1664 | Type::outputPost(OS, *SymbolType); | |||
1665 | ||||
1666 | // Null terminate the buffer. | |||
1667 | OS << '\0'; | |||
1668 | } | |||
1669 | ||||
1670 | char *llvm::microsoftDemangle(const char *MangledName, char *Buf, size_t *N, | |||
1671 | int *Status) { | |||
1672 | OutputStream OS = OutputStream::create(Buf, N, 1024); | |||
1673 | ||||
1674 | Demangler D(OS, StringView(MangledName)); | |||
1675 | D.parse(); | |||
| ||||
1676 | ||||
1677 | if (D.Error) | |||
1678 | *Status = llvm::demangle_invalid_mangled_name; | |||
1679 | else | |||
1680 | *Status = llvm::demangle_success; | |||
1681 | ||||
1682 | D.output(); | |||
1683 | return OS.getBuffer(); | |||
1684 | } |