Bug Summary

File:tools/lldb/source/Utility/FastDemangle.cpp
Warning:line 357, column 5
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name FastDemangle.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D HAVE_ROUND -D LLDB_CONFIGURATION_RELEASE -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/tools/lldb/source/Utility -I /build/llvm-toolchain-snapshot-7~svn338205/tools/lldb/source/Utility -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/tools/lldb/include -I /build/llvm-toolchain-snapshot-7~svn338205/tools/lldb/include -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn338205/include -I /usr/include/python2.7 -I /build/llvm-toolchain-snapshot-7~svn338205/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-7~svn338205/tools/lldb/source/. -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/lib/gcc/x86_64-linux-gnu/8/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-comment -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-deprecated-register -Wno-vla-extension -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/tools/lldb/source/Utility -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-07-29-043837-17923-1 -x c++ /build/llvm-toolchain-snapshot-7~svn338205/tools/lldb/source/Utility/FastDemangle.cpp -faddrsig
1//===-- FastDemangle.cpp ----------------------------------------*- C++ -*-===//
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#include "lldb/Utility/FastDemangle.h"
11
12#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH
13
14#include <functional>
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19
20//#define DEBUG_FAILURES 1
21//#define DEBUG_SUBSTITUTIONS 1
22//#define DEBUG_TEMPLATE_ARGS 1
23//#define DEBUG_HIGHWATER 1
24//#define DEBUG_REORDERING 1
25
26namespace {
27
28/// Represents the collection of qualifiers on a type
29
30enum Qualifiers {
31 QualifierNone = 0,
32 QualifierConst = 1,
33 QualifierRestrict = 2,
34 QualifierVolatile = 4,
35 QualifierReference = 8,
36 QualifierRValueReference = 16,
37 QualifierPointer = 32
38};
39
40/// Categorizes the recognized operators
41
42enum class OperatorKind {
43 Unary,
44 Postfix,
45 Binary,
46 Ternary,
47 Other,
48 ConversionOperator,
49 Vendor,
50 NoMatch
51};
52
53/// Represents one of the recognized two-character operator abbreviations used
54/// when parsing operators as names and expressions
55
56struct Operator {
57 const char *name;
58 OperatorKind kind;
59};
60
61/// Represents a range of characters in the output buffer, typically for use
62/// with RewriteRange()
63
64struct BufferRange {
65 int offset;
66 int length;
67};
68
69/// Transient state required while parsing a name
70
71struct NameState {
72 bool parse_function_params;
73 bool is_last_generic;
74 bool has_no_return_type;
75 BufferRange last_name_range;
76};
77
78/// LLDB's fast C++ demangler
79///
80/// This is an incomplete implementation designed to speed up the demangling
81/// process that is often a bottleneck when LLDB stops a process for the first
82/// time. Where the implementation doesn't know how to demangle a symbol it
83/// fails gracefully to allow the caller to fall back to the existing
84/// demangler.
85///
86/// Over time the full mangling spec should be supported without compromising
87/// performance for the most common cases.
88
89class SymbolDemangler {
90public:
91 //----------------------------------------------------
92 // Public API
93 //----------------------------------------------------
94
95 /// Create a SymbolDemangler
96 ///
97 /// The newly created demangler allocates and owns scratch memory sufficient
98 /// for demangling typical symbols. Additional memory will be allocated if
99 /// needed and managed by the demangler instance.
100
101 SymbolDemangler() {
102 m_buffer = (char *)malloc(8192);
103 m_buffer_end = m_buffer + 8192;
104 m_owns_buffer = true;
105
106 m_rewrite_ranges = (BufferRange *)malloc(128 * sizeof(BufferRange));
107 m_rewrite_ranges_size = 128;
108 m_owns_m_rewrite_ranges = true;
109 }
110
111 /// Create a SymbolDemangler that uses provided scratch memory
112 ///
113 /// The provided memory is not owned by the demangler. It will be
114 /// overwritten during calls to GetDemangledCopy() but can be used for other
115 /// purposes between calls. The provided memory will not be freed when this
116 /// instance is destroyed.
117 ///
118 /// If demangling a symbol requires additional space it will be allocated
119 /// and managed by the demangler instance.
120 ///
121 /// @param storage_ptr Valid pointer to at least storage_size bytes of space
122 /// that the SymbolDemangler can use during demangling
123 ///
124 /// @param storage_size Number of bytes of space available scratch memory
125 /// referenced by storage_ptr
126
127 SymbolDemangler(void *storage_ptr, size_t storage_size,
128 std::function<void(const char *)> builtins_hook = nullptr)
129 : m_builtins_hook(builtins_hook) {
130 // Use up to 1/8th of the provided space for rewrite ranges
131 m_rewrite_ranges_size = (storage_size >> 3) / sizeof(BufferRange);
132 m_rewrite_ranges = (BufferRange *)storage_ptr;
133 m_owns_m_rewrite_ranges = false;
134
135 // Use the rest for the character buffer
136 m_buffer =
137 (char *)storage_ptr + m_rewrite_ranges_size * sizeof(BufferRange);
138 m_buffer_end = (const char *)storage_ptr + storage_size;
139 m_owns_buffer = false;
140 }
141
142 /// Destroys the SymbolDemangler and deallocates any scratch memory that it
143 /// owns
144
145 ~SymbolDemangler() {
146 if (m_owns_buffer)
147 free(m_buffer);
148 if (m_owns_m_rewrite_ranges)
149 free(m_rewrite_ranges);
150 }
151
152#ifdef DEBUG_HIGHWATER
153 int highwater_store = 0;
154 int highwater_buffer = 0;
155#endif
156
157 /// Parses the provided mangled name and returns a newly allocated
158 /// demangling
159 ///
160 /// @param mangled_name Valid null-terminated C++ mangled name following the
161 /// Itanium C++ ABI mangling specification as implemented by Clang
162 ///
163 /// @result Newly allocated null-terminated demangled name when demangling
164 /// is successful, and nullptr when demangling fails. The caller is
165 /// responsible for freeing the allocated memory.
166
167 char *GetDemangledCopy(const char *mangled_name,
168 long mangled_name_length = 0) {
169 if (!ParseMangling(mangled_name, mangled_name_length))
170 return nullptr;
171
172#ifdef DEBUG_HIGHWATER
173 int rewrite_count = m_next_substitute_index +
174 (m_rewrite_ranges_size - 1 - m_next_template_arg_index);
175 int buffer_size = (int)(m_write_ptr - m_buffer);
176 if (rewrite_count > highwater_store)
177 highwater_store = rewrite_count;
178 if (buffer_size > highwater_buffer)
179 highwater_buffer = buffer_size;
180#endif
181
182 int length = (int)(m_write_ptr - m_buffer);
183 char *copy = (char *)malloc(length + 1);
184 memcpy(copy, m_buffer, length);
185 copy[length] = '\0';
186 return copy;
187 }
188
189private:
190 //----------------------------------------------------
191 // Grow methods
192 //
193 // Manage the storage used during demangling
194 //----------------------------------------------------
195
196 void GrowBuffer(long min_growth = 0) {
197 // By default, double the size of the buffer
198 long growth = m_buffer_end - m_buffer;
199
200 // Avoid growing by more than 1MB at a time
201 if (growth > 1 << 20)
18
Taking false branch
202 growth = 1 << 20;
203
204 // ... but never grow by less than requested, or 1K, whichever is greater
205 if (min_growth < 1024)
19
Assuming 'min_growth' is >= 1024
20
Taking false branch
206 min_growth = 1024;
207 if (growth < min_growth)
21
Assuming 'growth' is >= 'min_growth'
22
Taking false branch
208 growth = min_growth;
209
210 // Allocate the new m_buffer and migrate content
211 long new_size = (m_buffer_end - m_buffer) + growth;
212 char *new_buffer = (char *)malloc(new_size);
213 memcpy(new_buffer, m_buffer, m_write_ptr - m_buffer);
214 if (m_owns_buffer)
23
Assuming the condition is true
24
Taking true branch
215 free(m_buffer);
25
Memory is released
216 m_owns_buffer = true;
217
218 // Update references to the new buffer
219 m_write_ptr = new_buffer + (m_write_ptr - m_buffer);
220 m_buffer = new_buffer;
221 m_buffer_end = m_buffer + new_size;
222 }
223
224 void GrowRewriteRanges() {
225 // By default, double the size of the array
226 int growth = m_rewrite_ranges_size;
227
228 // Apply reasonable minimum and maximum sizes for growth
229 if (growth > 128)
230 growth = 128;
231 if (growth < 16)
232 growth = 16;
233
234 // Allocate the new array and migrate content
235 int bytes = (m_rewrite_ranges_size + growth) * sizeof(BufferRange);
236 BufferRange *new_ranges = (BufferRange *)malloc(bytes);
237 for (int index = 0; index < m_next_substitute_index; index++) {
238 new_ranges[index] = m_rewrite_ranges[index];
239 }
240 for (int index = m_rewrite_ranges_size - 1;
241 index > m_next_template_arg_index; index--) {
242 new_ranges[index + growth] = m_rewrite_ranges[index];
243 }
244 if (m_owns_m_rewrite_ranges)
245 free(m_rewrite_ranges);
246 m_owns_m_rewrite_ranges = true;
247
248 // Update references to the new array
249 m_rewrite_ranges = new_ranges;
250 m_rewrite_ranges_size += growth;
251 m_next_template_arg_index += growth;
252 }
253
254 //----------------------------------------------------
255 // Range and state management
256 //----------------------------------------------------
257
258 int GetStartCookie() { return (int)(m_write_ptr - m_buffer); }
259
260 BufferRange EndRange(int start_cookie) {
261 return {start_cookie, (int)(m_write_ptr - (m_buffer + start_cookie))};
262 }
263
264 void ReorderRange(BufferRange source_range, int insertion_point_cookie) {
265 // Ensure there's room the preserve the source range
266 if (m_write_ptr + source_range.length > m_buffer_end) {
267 GrowBuffer(m_write_ptr + source_range.length - m_buffer_end);
268 }
269
270 // Reorder the content
271 memcpy(m_write_ptr, m_buffer + source_range.offset, source_range.length);
272 memmove(m_buffer + insertion_point_cookie + source_range.length,
273 m_buffer + insertion_point_cookie,
274 source_range.offset - insertion_point_cookie);
275 memcpy(m_buffer + insertion_point_cookie, m_write_ptr, source_range.length);
276
277 // Fix up rewritable ranges, covering both substitutions and templates
278 int index = 0;
279 while (true) {
280 if (index == m_next_substitute_index)
281 index = m_next_template_arg_index + 1;
282 if (index == m_rewrite_ranges_size)
283 break;
284
285 // Affected ranges are either shuffled forward when after the insertion
286 // but before the source, or backward when inside the source
287 int candidate_offset = m_rewrite_ranges[index].offset;
288 if (candidate_offset >= insertion_point_cookie) {
289 if (candidate_offset < source_range.offset) {
290 m_rewrite_ranges[index].offset += source_range.length;
291 } else if (candidate_offset >= source_range.offset) {
292 m_rewrite_ranges[index].offset -=
293 (source_range.offset - insertion_point_cookie);
294 }
295 }
296 ++index;
297 }
298 }
299
300 void EndSubstitution(int start_cookie) {
301 if (m_next_substitute_index == m_next_template_arg_index)
302 GrowRewriteRanges();
303
304 int index = m_next_substitute_index++;
305 m_rewrite_ranges[index] = EndRange(start_cookie);
306#ifdef DEBUG_SUBSTITUTIONS
307 printf("Saved substitution # %d = %.*s\n", index,
308 m_rewrite_ranges[index].length, m_buffer + start_cookie);
309#endif
310 }
311
312 void EndTemplateArg(int start_cookie) {
313 if (m_next_substitute_index == m_next_template_arg_index)
314 GrowRewriteRanges();
315
316 int index = m_next_template_arg_index--;
317 m_rewrite_ranges[index] = EndRange(start_cookie);
318#ifdef DEBUG_TEMPLATE_ARGS
319 printf("Saved template arg # %d = %.*s\n",
320 m_rewrite_ranges_size - index - 1, m_rewrite_ranges[index].length,
321 m_buffer + start_cookie);
322#endif
323 }
324
325 void ResetTemplateArgs() {
326 // TODO: this works, but is it the right thing to do?
327 // Should we push/pop somehow at the call sites?
328 m_next_template_arg_index = m_rewrite_ranges_size - 1;
329 }
330
331 //----------------------------------------------------
332 // Write methods
333 //
334 // Appends content to the existing output buffer
335 //----------------------------------------------------
336
337 void Write(char character) {
338 if (m_write_ptr == m_buffer_end)
339 GrowBuffer();
340 *m_write_ptr++ = character;
341 }
342
343 void Write(const char *content) { Write(content, strlen(content)); }
344
345 void Write(const char *content, long content_length) {
346 char *end_m_write_ptr = m_write_ptr + content_length;
347 if (end_m_write_ptr > m_buffer_end) {
14
Taking true branch
348 if (content >= m_buffer && content < m_buffer_end) {
15
Assuming the condition is false
16
Taking false branch
349 long offset = content - m_buffer;
350 GrowBuffer(end_m_write_ptr - m_buffer_end);
351 content = m_buffer + offset;
352 } else {
353 GrowBuffer(end_m_write_ptr - m_buffer_end);
17
Calling 'SymbolDemangler::GrowBuffer'
26
Returning; memory was released
354 }
355 end_m_write_ptr = m_write_ptr + content_length;
356 }
357 memcpy(m_write_ptr, content, content_length);
27
Use of memory after it is freed
358 m_write_ptr = end_m_write_ptr;
359 }
360#define WRITE(x)Write(x, sizeof(x) - 1) Write(x, sizeof(x) - 1)
361
362 void WriteTemplateStart() { Write('<'); }
363
364 void WriteTemplateEnd() {
365 // Put a space between terminal > characters when nesting templates
366 if (m_write_ptr != m_buffer && *(m_write_ptr - 1) == '>')
367 WRITE(" >")Write(" >", sizeof(" >") - 1);
368 else
369 Write('>');
370 }
371
372 void WriteCommaSpace() { WRITE(", ")Write(", ", sizeof(", ") - 1); }
373
374 void WriteNamespaceSeparator() { WRITE("::")Write("::", sizeof("::") - 1); }
375
376 void WriteStdPrefix() { WRITE("std::")Write("std::", sizeof("std::") - 1); }
377
378 void WriteQualifiers(int qualifiers, bool space_before_reference = true) {
379 if (qualifiers & QualifierPointer)
380 Write('*');
381 if (qualifiers & QualifierConst)
382 WRITE(" const")Write(" const", sizeof(" const") - 1);
383 if (qualifiers & QualifierVolatile)
384 WRITE(" volatile")Write(" volatile", sizeof(" volatile") - 1);
385 if (qualifiers & QualifierRestrict)
386 WRITE(" restrict")Write(" restrict", sizeof(" restrict") - 1);
387 if (qualifiers & QualifierReference) {
388 if (space_before_reference)
389 WRITE(" &")Write(" &", sizeof(" &") - 1);
390 else
391 Write('&');
392 }
393 if (qualifiers & QualifierRValueReference) {
394 if (space_before_reference)
395 WRITE(" &&")Write(" &&", sizeof(" &&") - 1);
396 else
397 WRITE("&&")Write("&&", sizeof("&&") - 1);
398 }
399 }
400
401 //----------------------------------------------------
402 // Rewrite methods
403 //
404 // Write another copy of content already present earlier in the output buffer
405 //----------------------------------------------------
406
407 void RewriteRange(BufferRange range) {
408 Write(m_buffer + range.offset, range.length);
13
Calling 'SymbolDemangler::Write'
409 }
410
411 bool RewriteSubstitution(int index) {
412 if (index < 0 || index >= m_next_substitute_index) {
413#ifdef DEBUG_FAILURES
414 printf("*** Invalid substitution #%d\n", index);
415#endif
416 return false;
417 }
418 RewriteRange(m_rewrite_ranges[index]);
419 return true;
420 }
421
422 bool RewriteTemplateArg(int template_index) {
423 int index = m_rewrite_ranges_size - 1 - template_index;
424 if (template_index < 0 || index <= m_next_template_arg_index) {
425#ifdef DEBUG_FAILURES
426 printf("*** Invalid template arg reference #%d\n", template_index);
427#endif
428 return false;
429 }
430 RewriteRange(m_rewrite_ranges[index]);
431 return true;
432 }
433
434 //----------------------------------------------------
435 // TryParse methods
436 //
437 // Provide information with return values instead of writing to the output
438 // buffer
439 //
440 // Values indicating failure guarantee that the pre- call m_read_ptr is
441 // unchanged
442 //----------------------------------------------------
443
444 int TryParseNumber() {
445 unsigned char digit = *m_read_ptr - '0';
446 if (digit > 9)
447 return -1;
448
449 int count = digit;
450 while (true) {
451 digit = *++m_read_ptr - '0';
452 if (digit > 9)
453 break;
454
455 count = count * 10 + digit;
456 }
457 return count;
458 }
459
460 int TryParseBase36Number() {
461 char digit = *m_read_ptr;
462 int count;
463 if (digit >= '0' && digit <= '9')
464 count = digit -= '0';
465 else if (digit >= 'A' && digit <= 'Z')
466 count = digit -= ('A' - 10);
467 else
468 return -1;
469
470 while (true) {
471 digit = *++m_read_ptr;
472 if (digit >= '0' && digit <= '9')
473 digit -= '0';
474 else if (digit >= 'A' && digit <= 'Z')
475 digit -= ('A' - 10);
476 else
477 break;
478
479 count = count * 36 + digit;
480 }
481 return count;
482 }
483
484 // <builtin-type> ::= v # void
485 // ::= w # wchar_t
486 // ::= b # bool
487 // ::= c # char
488 // ::= a # signed char
489 // ::= h # unsigned char
490 // ::= s # short
491 // ::= t # unsigned short
492 // ::= i # int
493 // ::= j # unsigned int
494 // ::= l # long
495 // ::= m # unsigned long
496 // ::= x # long long, __int64
497 // ::= y # unsigned long long, __int64
498 // ::= n # __int128
499 // ::= o # unsigned __int128
500 // ::= f # float
501 // ::= d # double
502 // ::= e # long double, __float80
503 // ::= g # __float128
504 // ::= z # ellipsis
505 // ::= Dd # IEEE 754r decimal floating point (64 bits)
506 // ::= De # IEEE 754r decimal floating point (128 bits)
507 // ::= Df # IEEE 754r decimal floating point (32 bits)
508 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
509 // ::= Di # char32_t
510 // ::= Ds # char16_t
511 // ::= Da # auto (in dependent new-expressions)
512 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
513 // ::= u <source-name> # vendor extended type
514
515 const char *TryParseBuiltinType() {
516 if (m_builtins_hook)
517 m_builtins_hook(m_read_ptr);
518
519 switch (*m_read_ptr++) {
520 case 'v':
521 return "void";
522 case 'w':
523 return "wchar_t";
524 case 'b':
525 return "bool";
526 case 'c':
527 return "char";
528 case 'a':
529 return "signed char";
530 case 'h':
531 return "unsigned char";
532 case 's':
533 return "short";
534 case 't':
535 return "unsigned short";
536 case 'i':
537 return "int";
538 case 'j':
539 return "unsigned int";
540 case 'l':
541 return "long";
542 case 'm':
543 return "unsigned long";
544 case 'x':
545 return "long long";
546 case 'y':
547 return "unsigned long long";
548 case 'n':
549 return "__int128";
550 case 'o':
551 return "unsigned __int128";
552 case 'f':
553 return "float";
554 case 'd':
555 return "double";
556 case 'e':
557 return "long double";
558 case 'g':
559 return "__float128";
560 case 'z':
561 return "...";
562 case 'D': {
563 switch (*m_read_ptr++) {
564 case 'd':
565 return "decimal64";
566 case 'e':
567 return "decimal128";
568 case 'f':
569 return "decimal32";
570 case 'h':
571 return "decimal16";
572 case 'i':
573 return "char32_t";
574 case 's':
575 return "char16_t";
576 case 'a':
577 return "auto";
578 case 'c':
579 return "decltype(auto)";
580 case 'n':
581 return "std::nullptr_t";
582 default:
583 --m_read_ptr;
584 }
585 }
586 }
587 --m_read_ptr;
588 return nullptr;
589 }
590
591 // <operator-name>
592 // ::= aa # &&
593 // ::= ad # & (unary)
594 // ::= an # &
595 // ::= aN # &=
596 // ::= aS # =
597 // ::= cl # ()
598 // ::= cm # ,
599 // ::= co # ~
600 // ::= da # delete[]
601 // ::= de # * (unary)
602 // ::= dl # delete
603 // ::= dv # /
604 // ::= dV # /=
605 // ::= eo # ^
606 // ::= eO # ^=
607 // ::= eq # ==
608 // ::= ge # >=
609 // ::= gt # >
610 // ::= ix # []
611 // ::= le # <=
612 // ::= ls # <<
613 // ::= lS # <<=
614 // ::= lt # <
615 // ::= mi # -
616 // ::= mI # -=
617 // ::= ml # *
618 // ::= mL # *=
619 // ::= mm # -- (postfix in <expression> context)
620 // ::= na # new[]
621 // ::= ne # !=
622 // ::= ng # - (unary)
623 // ::= nt # !
624 // ::= nw # new
625 // ::= oo # ||
626 // ::= or # |
627 // ::= oR # |=
628 // ::= pm # ->*
629 // ::= pl # +
630 // ::= pL # +=
631 // ::= pp # ++ (postfix in <expression> context)
632 // ::= ps # + (unary)
633 // ::= pt # ->
634 // ::= qu # ?
635 // ::= rm # %
636 // ::= rM # %=
637 // ::= rs # >>
638 // ::= rS # >>=
639 // ::= cv <type> # (cast)
640 // ::= v <digit> <source-name> # vendor extended
641 // operator
642
643 Operator TryParseOperator() {
644 switch (*m_read_ptr++) {
645 case 'a':
646 switch (*m_read_ptr++) {
647 case 'a':
648 return {"&&", OperatorKind::Binary};
649 case 'd':
650 return {"&", OperatorKind::Unary};
651 case 'n':
652 return {"&", OperatorKind::Binary};
653 case 'N':
654 return {"&=", OperatorKind::Binary};
655 case 'S':
656 return {"=", OperatorKind::Binary};
657 }
658 --m_read_ptr;
659 break;
660 case 'c':
661 switch (*m_read_ptr++) {
662 case 'l':
663 return {"()", OperatorKind::Other};
664 case 'm':
665 return {",", OperatorKind::Other};
666 case 'o':
667 return {"~", OperatorKind::Unary};
668 case 'v':
669 return {nullptr, OperatorKind::ConversionOperator};
670 }
671 --m_read_ptr;
672 break;
673 case 'd':
674 switch (*m_read_ptr++) {
675 case 'a':
676 return {" delete[]", OperatorKind::Other};
677 case 'e':
678 return {"*", OperatorKind::Unary};
679 case 'l':
680 return {" delete", OperatorKind::Other};
681 case 'v':
682 return {"/", OperatorKind::Binary};
683 case 'V':
684 return {"/=", OperatorKind::Binary};
685 }
686 --m_read_ptr;
687 break;
688 case 'e':
689 switch (*m_read_ptr++) {
690 case 'o':
691 return {"^", OperatorKind::Binary};
692 case 'O':
693 return {"^=", OperatorKind::Binary};
694 case 'q':
695 return {"==", OperatorKind::Binary};
696 }
697 --m_read_ptr;
698 break;
699 case 'g':
700 switch (*m_read_ptr++) {
701 case 'e':
702 return {">=", OperatorKind::Binary};
703 case 't':
704 return {">", OperatorKind::Binary};
705 }
706 --m_read_ptr;
707 break;
708 case 'i':
709 switch (*m_read_ptr++) {
710 case 'x':
711 return {"[]", OperatorKind::Other};
712 }
713 --m_read_ptr;
714 break;
715 case 'l':
716 switch (*m_read_ptr++) {
717 case 'e':
718 return {"<=", OperatorKind::Binary};
719 case 's':
720 return {"<<", OperatorKind::Binary};
721 case 'S':
722 return {"<<=", OperatorKind::Binary};
723 case 't':
724 return {"<", OperatorKind::Binary};
725 // case 'i': return { "?", OperatorKind::Binary };
726 }
727 --m_read_ptr;
728 break;
729 case 'm':
730 switch (*m_read_ptr++) {
731 case 'i':
732 return {"-", OperatorKind::Binary};
733 case 'I':
734 return {"-=", OperatorKind::Binary};
735 case 'l':
736 return {"*", OperatorKind::Binary};
737 case 'L':
738 return {"*=", OperatorKind::Binary};
739 case 'm':
740 return {"--", OperatorKind::Postfix};
741 }
742 --m_read_ptr;
743 break;
744 case 'n':
745 switch (*m_read_ptr++) {
746 case 'a':
747 return {" new[]", OperatorKind::Other};
748 case 'e':
749 return {"!=", OperatorKind::Binary};
750 case 'g':
751 return {"-", OperatorKind::Unary};
752 case 't':
753 return {"!", OperatorKind::Unary};
754 case 'w':
755 return {" new", OperatorKind::Other};
756 }
757 --m_read_ptr;
758 break;
759 case 'o':
760 switch (*m_read_ptr++) {
761 case 'o':
762 return {"||", OperatorKind::Binary};
763 case 'r':
764 return {"|", OperatorKind::Binary};
765 case 'R':
766 return {"|=", OperatorKind::Binary};
767 }
768 --m_read_ptr;
769 break;
770 case 'p':
771 switch (*m_read_ptr++) {
772 case 'm':
773 return {"->*", OperatorKind::Binary};
774 case 's':
775 return {"+", OperatorKind::Unary};
776 case 'l':
777 return {"+", OperatorKind::Binary};
778 case 'L':
779 return {"+=", OperatorKind::Binary};
780 case 'p':
781 return {"++", OperatorKind::Postfix};
782 case 't':
783 return {"->", OperatorKind::Binary};
784 }
785 --m_read_ptr;
786 break;
787 case 'q':
788 switch (*m_read_ptr++) {
789 case 'u':
790 return {"?", OperatorKind::Ternary};
791 }
792 --m_read_ptr;
793 break;
794 case 'r':
795 switch (*m_read_ptr++) {
796 case 'm':
797 return {"%", OperatorKind::Binary};
798 case 'M':
799 return {"%=", OperatorKind::Binary};
800 case 's':
801 return {">>", OperatorKind::Binary};
802 case 'S':
803 return {">=", OperatorKind::Binary};
804 }
805 --m_read_ptr;
806 break;
807 case 'v':
808 char digit = *m_read_ptr;
809 if (digit >= '0' && digit <= '9') {
810 m_read_ptr++;
811 return {nullptr, OperatorKind::Vendor};
812 }
813 --m_read_ptr;
814 break;
815 }
816 --m_read_ptr;
817 return {nullptr, OperatorKind::NoMatch};
818 }
819
820 // <CV-qualifiers> ::= [r] [V] [K]
821 // <ref-qualifier> ::= R # & ref-qualifier <ref-qualifier>
822 // ::= O # && ref-qualifier
823
824 int TryParseQualifiers(bool allow_cv, bool allow_ro) {
825 int qualifiers = QualifierNone;
826 char next = *m_read_ptr;
827 if (allow_cv) {
828 if (next == 'r') // restrict
829 {
830 qualifiers |= QualifierRestrict;
831 next = *++m_read_ptr;
832 }
833 if (next == 'V') // volatile
834 {
835 qualifiers |= QualifierVolatile;
836 next = *++m_read_ptr;
837 }
838 if (next == 'K') // const
839 {
840 qualifiers |= QualifierConst;
841 next = *++m_read_ptr;
842 }
843 }
844 if (allow_ro) {
845 if (next == 'R') {
846 ++m_read_ptr;
847 qualifiers |= QualifierReference;
848 } else if (next == 'O') {
849 ++m_read_ptr;
850 qualifiers |= QualifierRValueReference;
851 }
852 }
853 return qualifiers;
854 }
855
856 // <discriminator> := _ <non-negative number> # when number < 10
857 // := __ <non-negative number> _ # when number >= 10
858 // extension := decimal-digit+
859
860 int TryParseDiscriminator() {
861 const char *discriminator_start = m_read_ptr;
862
863 // Test the extension first, since it's what Clang uses
864 int discriminator_value = TryParseNumber();
865 if (discriminator_value != -1)
866 return discriminator_value;
867
868 char next = *m_read_ptr;
869 if (next == '_') {
870 next = *++m_read_ptr;
871 if (next == '_') {
872 ++m_read_ptr;
873 discriminator_value = TryParseNumber();
874 if (discriminator_value != -1 && *m_read_ptr++ != '_') {
875 return discriminator_value;
876 }
877 } else if (next >= '0' && next <= '9') {
878 ++m_read_ptr;
879 return next - '0';
880 }
881 }
882
883 // Not a valid discriminator
884 m_read_ptr = discriminator_start;
885 return -1;
886 }
887
888 //----------------------------------------------------
889 // Parse methods
890 //
891 // Consume input starting from m_read_ptr and produce buffered output at
892 // m_write_ptr
893 //
894 // Failures return false and may leave m_read_ptr in an indeterminate state
895 //----------------------------------------------------
896
897 bool Parse(char character) {
898 if (*m_read_ptr++ == character)
899 return true;
900#ifdef DEBUG_FAILURES
901 printf("*** Expected '%c'\n", character);
902#endif
903 return false;
904 }
905
906 // <number> ::= [n] <non-negative decimal integer>
907
908 bool ParseNumber(bool allow_negative = false) {
909 if (allow_negative && *m_read_ptr == 'n') {
910 Write('-');
911 ++m_read_ptr;
912 }
913 const char *before_digits = m_read_ptr;
914 while (true) {
915 unsigned char digit = *m_read_ptr - '0';
916 if (digit > 9)
917 break;
918 ++m_read_ptr;
919 }
920 if (int digit_count = (int)(m_read_ptr - before_digits)) {
921 Write(before_digits, digit_count);
922 return true;
923 }
924#ifdef DEBUG_FAILURES
925 printf("*** Expected number\n");
926#endif
927 return false;
928 }
929
930 // <substitution> ::= S <seq-id> _
931 // ::= S_
932 // <substitution> ::= Sa # ::std::allocator <substitution> ::= Sb #
933 // ::std::basic_string <substitution> ::= Ss # ::std::basic_string < char,
934 // ::std::char_traits<char>,
935 // ::std::allocator<char> >
936 // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char>
937 // > <substitution> ::= So # ::std::basic_ostream<char,
938 // std::char_traits<char> > <substitution> ::= Sd #
939 // ::std::basic_iostream<char, std::char_traits<char> >
940
941 bool ParseSubstitution() {
942 const char *substitution;
943 switch (*m_read_ptr) {
944 case 'a':
945 substitution = "std::allocator";
946 break;
947 case 'b':
948 substitution = "std::basic_string";
949 break;
950 case 's':
951 substitution = "std::string";
952 break;
953 case 'i':
954 substitution = "std::istream";
955 break;
956 case 'o':
957 substitution = "std::ostream";
958 break;
959 case 'd':
960 substitution = "std::iostream";
961 break;
962 default:
963 // A failed attempt to parse a number will return -1 which turns out to be
964 // perfect here as S_ is the first substitution, S0_ the next and so
965 // forth
966 int substitution_index = TryParseBase36Number();
967 if (*m_read_ptr++ != '_') {
968#ifdef DEBUG_FAILURES
969 printf("*** Expected terminal _ in substitution\n");
970#endif
971 return false;
972 }
973 return RewriteSubstitution(substitution_index + 1);
974 }
975 Write(substitution);
976 ++m_read_ptr;
977 return true;
978 }
979
980 // <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
981 //
982 // <bare-function-type> ::= <signature type>+ # types are possible
983 // return type, then parameter types
984
985 bool ParseFunctionType(int inner_qualifiers = QualifierNone) {
986#ifdef DEBUG_FAILURES
987 printf("*** Function types not supported\n");
988#endif
989 // TODO: first steps toward an implementation follow, but they're far
990 // from complete. Function types tend to bracket other types eg: int (*)()
991 // when used as the type for "name" becomes int (*name)(). This makes
992 // substitution et al ... interesting.
993 return false;
994
995#if 0 // TODO
996 if (*m_read_ptr == 'Y')
997 ++m_read_ptr;
998
999 int return_type_start_cookie = GetStartCookie();
1000 if (!ParseType())
1001 return false;
1002 Write(' ');
1003
1004 int insert_cookie = GetStartCookie();
1005 Write('(');
1006 bool first_param = true;
1007 int qualifiers = QualifierNone;
1008 while (true)
1009 {
1010 switch (*m_read_ptr)
1011 {
1012 case 'E':
1013 ++m_read_ptr;
1014 Write(')');
1015 break;
1016 case 'v':
1017 ++m_read_ptr;
1018 continue;
1019 case 'R':
1020 case 'O':
1021 if (*(m_read_ptr + 1) == 'E')
1022 {
1023 qualifiers = TryParseQualifiers (false, true);
1024 Parse('E');
1025 break;
1026 }
1027 // fallthrough
1028 default:
1029 {
1030 if (first_param)
1031 first_param = false;
1032 else WriteCommaSpace();
1033
1034 if (!ParseType())
1035 return false;
1036 continue;
1037 }
1038 }
1039 break;
1040 }
1041
1042 if (qualifiers)
1043 {
1044 WriteQualifiers (qualifiers);
1045 EndSubstitution (return_type_start_cookie);
1046 }
1047
1048 if (inner_qualifiers)
1049 {
1050 int qualifier_start_cookie = GetStartCookie();
1051 Write ('(');
1052 WriteQualifiers (inner_qualifiers);
1053 Write (')');
1054 ReorderRange (EndRange (qualifier_start_cookie), insert_cookie);
1055 }
1056 return true;
1057#endif // TODO
1058 }
1059
1060 // <array-type> ::= A <positive dimension number> _ <element type>
1061 // ::= A [<dimension expression>] _ <element type>
1062
1063 bool ParseArrayType(int qualifiers = QualifierNone) {
1064#ifdef DEBUG_FAILURES
1065 printf("*** Array type unsupported\n");
1066#endif
1067 // TODO: We fail horribly when recalling these as substitutions or
1068 // templates and trying to constify them eg:
1069 // _ZN4llvm2cl5applyIA28_cNS0_3optIbLb0ENS0_6parserIbEEEEEEvRKT_PT0_
1070 //
1071 // TODO: Chances are we don't do any better with references and pointers
1072 // that should be type (&) [] instead of type & []
1073
1074 return false;
1075
1076#if 0 // TODO
1077 if (*m_read_ptr == '_')
1078 {
1079 ++m_read_ptr;
1080 if (!ParseType())
1081 return false;
1082 if (qualifiers)
1083 WriteQualifiers(qualifiers);
1084 WRITE(" []")Write(" []", sizeof(" []") - 1);
1085 return true;
1086 }
1087 else
1088 {
1089 const char *before_digits = m_read_ptr;
1090 if (TryParseNumber() != -1)
1091 {
1092 const char *after_digits = m_read_ptr;
1093 if (!Parse('_'))
1094 return false;
1095 if (!ParseType())
1096 return false;
1097 if (qualifiers)
1098 WriteQualifiers(qualifiers);
1099 Write(' ');
1100 Write('[');
1101 Write(before_digits, after_digits - before_digits);
1102 }
1103 else
1104 {
1105 int type_insertion_cookie = GetStartCookie();
1106 if (!ParseExpression())
1107 return false;
1108 if (!Parse('_'))
1109 return false;
1110
1111 int type_start_cookie = GetStartCookie();
1112 if (!ParseType())
1113 return false;
1114 if (qualifiers)
1115 WriteQualifiers(qualifiers);
1116 Write(' ');
1117 Write('[');
1118 ReorderRange (EndRange (type_start_cookie), type_insertion_cookie);
1119 }
1120 Write(']');
1121 return true;
1122 }
1123#endif // TODO
1124 }
1125
1126 // <pointer-to-member-type> ::= M <class type> <member type>
1127
1128 // TODO: Determine how to handle pointers to function members correctly,
1129 // currently not an issue because we don't have function types at all...
1130 bool ParsePointerToMemberType() {
1131 int insertion_cookie = GetStartCookie();
1132 Write(' ');
1133 if (!ParseType())
1134 return false;
1135 WRITE("::*")Write("::*", sizeof("::*") - 1);
1136
1137 int type_cookie = GetStartCookie();
1138 if (!ParseType())
1139 return false;
1140 ReorderRange(EndRange(type_cookie), insertion_cookie);
1141 return true;
1142 }
1143
1144 // <template-param> ::= T_ # first template parameter
1145 // ::= T <parameter-2 non-negative number> _
1146
1147 bool ParseTemplateParam() {
1148 int count = TryParseNumber();
1149 if (!Parse('_'))
1150 return false;
1151
1152 // When no number is present we get -1, which is convenient since T_ is the
1153 // zeroth element T0_ is element 1, and so on
1154 return RewriteTemplateArg(count + 1);
1155 }
1156
1157 // <vector-type>
1158 // Dv <dimension number> _ <vector type>
1159 bool TryParseVectorType() {
1160 const int dimension = TryParseNumber();
1161 if (dimension == -1)
1162 return false;
1163
1164 if (*m_read_ptr++ != '_')
1165 return false;
1166
1167 char vec_dimens[32] = {'\0'};
1168 ::snprintf(vec_dimens, sizeof vec_dimens - 1, " __vector(%d)", dimension);
1169 ParseType();
1170 Write(vec_dimens);
1171 return true;
1172 }
1173
1174 // <type> ::= <builtin-type>
1175 // ::= <function-type>
1176 // ::= <class-enum-type>
1177 // ::= <array-type>
1178 // ::= <pointer-to-member-type>
1179 // ::= <template-param>
1180 // ::= <template-template-param> <template-args>
1181 // ::= <decltype>
1182 // ::= <substitution>
1183 // ::= <CV-qualifiers> <type>
1184 // ::= P <type> # pointer-to
1185 // ::= R <type> # reference-to
1186 // ::= O <type> # rvalue reference-to (C++0x)
1187 // ::= C <type> # complex pair (C 2000)
1188 // ::= G <type> # imaginary (C 2000)
1189 // ::= Dp <type> # pack expansion (C++0x)
1190 // ::= U <source-name> <type> # vendor extended type qualifier
1191 // extension := U <objc-name> <objc-type> # objc-type<identifier> extension
1192 // := <vector-type> # <vector-type> starts with Dv
1193
1194 // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 +
1195 // <number of digits in k1> + k1 <objc-type> := <source-name> #
1196 // PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-
1197 // name>
1198
1199 bool ParseType() {
1200#ifdef DEBUG_FAILURES
1201 const char *failed_type = m_read_ptr;
1202#endif
1203 int type_start_cookie = GetStartCookie();
1204 bool suppress_substitution = false;
1205
1206 int qualifiers = TryParseQualifiers(true, false);
1207 switch (*m_read_ptr) {
1208 case 'D':
1209 ++m_read_ptr;
1210 switch (*m_read_ptr++) {
1211 case 'p':
1212 if (!ParseType())
1213 return false;
1214 break;
1215 case 'v':
1216 if (!TryParseVectorType())
1217 return false;
1218 break;
1219 case 'T':
1220 case 't':
1221 default:
1222#ifdef DEBUG_FAILURES
1223 printf("*** Unsupported type: %.3s\n", failed_type);
1224#endif
1225 return false;
1226 }
1227 break;
1228 case 'T':
1229 ++m_read_ptr;
1230 if (!ParseTemplateParam())
1231 return false;
1232 break;
1233 case 'M':
1234 ++m_read_ptr;
1235 if (!ParsePointerToMemberType())
1236 return false;
1237 break;
1238 case 'A':
1239 ++m_read_ptr;
1240 if (!ParseArrayType())
1241 return false;
1242 break;
1243 case 'F':
1244 ++m_read_ptr;
1245 if (!ParseFunctionType())
1246 return false;
1247 break;
1248 case 'S':
1249 if (*++m_read_ptr == 't') {
1250 ++m_read_ptr;
1251 WriteStdPrefix();
1252 if (!ParseName())
1253 return false;
1254 } else {
1255 suppress_substitution = true;
1256 if (!ParseSubstitution())
1257 return false;
1258 }
1259 break;
1260 case 'P': {
1261 switch (*++m_read_ptr) {
1262 case 'F':
1263 ++m_read_ptr;
1264 if (!ParseFunctionType(QualifierPointer))
1265 return false;
1266 break;
1267 default:
1268 if (!ParseType())
1269 return false;
1270 Write('*');
1271 break;
1272 }
1273 break;
1274 }
1275 case 'R': {
1276 ++m_read_ptr;
1277 if (!ParseType())
1278 return false;
1279 Write('&');
1280 break;
1281 }
1282 case 'O': {
1283 ++m_read_ptr;
1284 if (!ParseType())
1285 return false;
1286 Write('&');
1287 Write('&');
1288 break;
1289 }
1290 case 'C':
1291 case 'G':
1292 case 'U':
1293#ifdef DEBUG_FAILURES
1294 printf("*** Unsupported type: %.3s\n", failed_type);
1295#endif
1296 return false;
1297 // Test for common cases to avoid TryParseBuiltinType() overhead
1298 case 'N':
1299 case 'Z':
1300 case 'L':
1301 if (!ParseName())
1302 return false;
1303 break;
1304 default:
1305 if (const char *builtin = TryParseBuiltinType()) {
1306 Write(builtin);
1307 suppress_substitution = true;
1308 } else {
1309 if (!ParseName())
1310 return false;
1311 }
1312 break;
1313 }
1314
1315 // Allow base substitutions to be suppressed, but always record
1316 // substitutions for the qualified variant
1317 if (!suppress_substitution)
1318 EndSubstitution(type_start_cookie);
1319 if (qualifiers) {
1320 WriteQualifiers(qualifiers, false);
1321 EndSubstitution(type_start_cookie);
1322 }
1323 return true;
1324 }
1325
1326 // <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
1327 // ::= <closure-type-name>
1328 //
1329 // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
1330 //
1331 // <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda
1332 // has no parameters
1333
1334 bool ParseUnnamedTypeName(NameState &name_state) {
1335 switch (*m_read_ptr++) {
1336 case 't': {
1337 int cookie = GetStartCookie();
1338 WRITE("'unnamed")Write("'unnamed", sizeof("'unnamed") - 1);
1339 const char *before_digits = m_read_ptr;
1340 if (TryParseNumber() != -1)
1341 Write(before_digits, m_read_ptr - before_digits);
1342 if (!Parse('_'))
1343 return false;
1344 Write('\'');
1345 name_state.last_name_range = EndRange(cookie);
1346 return true;
1347 }
1348 case 'b': {
1349 int cookie = GetStartCookie();
1350 WRITE("'block")Write("'block", sizeof("'block") - 1);
1351 const char *before_digits = m_read_ptr;
1352 if (TryParseNumber() != -1)
1353 Write(before_digits, m_read_ptr - before_digits);
1354 if (!Parse('_'))
1355 return false;
1356 Write('\'');
1357 name_state.last_name_range = EndRange(cookie);
1358 return true;
1359 }
1360 case 'l':
1361#ifdef DEBUG_FAILURES
1362 printf("*** Lambda type names unsupported\n");
1363#endif
1364 return false;
1365 }
1366#ifdef DEBUG_FAILURES
1367 printf("*** Unknown unnamed type %.3s\n", m_read_ptr - 2);
1368#endif
1369 return false;
1370 }
1371
1372 // <ctor-dtor-name> ::= C1 # complete object constructor
1373 // ::= C2 # base object constructor
1374 // ::= C3 # complete object allocating constructor
1375
1376 bool ParseCtor(NameState &name_state) {
1377 char next = *m_read_ptr;
1378 if (next == '1' || next == '2' || next == '3' || next == '5') {
7
Assuming the condition is false
8
Assuming the condition is false
9
Assuming the condition is false
10
Assuming the condition is true
11
Taking true branch
1379 RewriteRange(name_state.last_name_range);
12
Calling 'SymbolDemangler::RewriteRange'
1380 name_state.has_no_return_type = true;
1381 ++m_read_ptr;
1382 return true;
1383 }
1384#ifdef DEBUG_FAILURES
1385 printf("*** Broken constructor\n");
1386#endif
1387 return false;
1388 }
1389
1390 // <ctor-dtor-name> ::= D0 # deleting destructor
1391 // ::= D1 # complete object destructor
1392 // ::= D2 # base object destructor
1393
1394 bool ParseDtor(NameState &name_state) {
1395 char next = *m_read_ptr;
1396 if (next == '0' || next == '1' || next == '2' || next == '5') {
1397 Write('~');
1398 RewriteRange(name_state.last_name_range);
1399 name_state.has_no_return_type = true;
1400 ++m_read_ptr;
1401 return true;
1402 }
1403#ifdef DEBUG_FAILURES
1404 printf("*** Broken destructor\n");
1405#endif
1406 return false;
1407 }
1408
1409 // See TryParseOperator()
1410
1411 bool ParseOperatorName(NameState &name_state) {
1412#ifdef DEBUG_FAILURES
1413 const char *operator_ptr = m_read_ptr;
1414#endif
1415 Operator parsed_operator = TryParseOperator();
1416 if (parsed_operator.name) {
1417 WRITE("operator")Write("operator", sizeof("operator") - 1);
1418 Write(parsed_operator.name);
1419 return true;
1420 }
1421
1422 // Handle special operators
1423 switch (parsed_operator.kind) {
1424 case OperatorKind::Vendor:
1425 WRITE("operator ")Write("operator ", sizeof("operator ") - 1);
1426 return ParseSourceName();
1427 case OperatorKind::ConversionOperator:
1428 ResetTemplateArgs();
1429 name_state.has_no_return_type = true;
1430 WRITE("operator ")Write("operator ", sizeof("operator ") - 1);
1431 return ParseType();
1432 default:
1433#ifdef DEBUG_FAILURES
1434 printf("*** Unknown operator: %.2s\n", operator_ptr);
1435#endif
1436 return false;
1437 }
1438 }
1439
1440 // <source-name> ::= <positive length number> <identifier>
1441
1442 bool ParseSourceName() {
1443 int count = TryParseNumber();
1444 if (count == -1) {
1445#ifdef DEBUG_FAILURES
1446 printf("*** Malformed source name, missing length count\n");
1447#endif
1448 return false;
1449 }
1450
1451 const char *next_m_read_ptr = m_read_ptr + count;
1452 if (next_m_read_ptr > m_read_end) {
1453#ifdef DEBUG_FAILURES
1454 printf("*** Malformed source name, premature termination\n");
1455#endif
1456 return false;
1457 }
1458
1459 if (count >= 10 && strncmp(m_read_ptr, "_GLOBAL__N", 10) == 0)
1460 WRITE("(anonymous namespace)")Write("(anonymous namespace)", sizeof("(anonymous namespace)"
) - 1)
;
1461 else
1462 Write(m_read_ptr, count);
1463
1464 m_read_ptr = next_m_read_ptr;
1465 return true;
1466 }
1467
1468 // <unqualified-name> ::= <operator-name>
1469 // ::= <ctor-dtor-name>
1470 // ::= <source-name>
1471 // ::= <unnamed-type-name>
1472
1473 bool ParseUnqualifiedName(NameState &name_state) {
1474 // Note that these are detected directly in ParseNestedName for performance
1475 // rather than switching on the same options twice
1476 char next = *m_read_ptr;
1477 switch (next) {
5
Control jumps to 'case 67:' at line 1478
1478 case 'C':
1479 ++m_read_ptr;
1480 return ParseCtor(name_state);
6
Calling 'SymbolDemangler::ParseCtor'
1481 case 'D':
1482 ++m_read_ptr;
1483 return ParseDtor(name_state);
1484 case 'U':
1485 ++m_read_ptr;
1486 return ParseUnnamedTypeName(name_state);
1487 case '0':
1488 case '1':
1489 case '2':
1490 case '3':
1491 case '4':
1492 case '5':
1493 case '6':
1494 case '7':
1495 case '8':
1496 case '9': {
1497 int name_start_cookie = GetStartCookie();
1498 if (!ParseSourceName())
1499 return false;
1500 name_state.last_name_range = EndRange(name_start_cookie);
1501 return true;
1502 }
1503 default:
1504 return ParseOperatorName(name_state);
1505 };
1506 }
1507
1508 // <unscoped-name> ::= <unqualified-name>
1509 // ::= St <unqualified-name> # ::std::
1510 // extension ::= StL<unqualified-name>
1511
1512 bool ParseUnscopedName(NameState &name_state) {
1513 if (*m_read_ptr == 'S' && *(m_read_ptr + 1) == 't') {
1514 WriteStdPrefix();
1515 if (*(m_read_ptr += 2) == 'L')
1516 ++m_read_ptr;
1517 }
1518 return ParseUnqualifiedName(name_state);
1519 }
1520
1521 bool ParseIntegerLiteral(const char *prefix, const char *suffix,
1522 bool allow_negative) {
1523 if (prefix)
1524 Write(prefix);
1525 if (!ParseNumber(allow_negative))
1526 return false;
1527 if (suffix)
1528 Write(suffix);
1529 return Parse('E');
1530 }
1531
1532 bool ParseBooleanLiteral() {
1533 switch (*m_read_ptr++) {
1534 case '0':
1535 WRITE("false")Write("false", sizeof("false") - 1);
1536 break;
1537 case '1':
1538 WRITE("true")Write("true", sizeof("true") - 1);
1539 break;
1540 default:
1541#ifdef DEBUG_FAILURES
1542 printf("*** Boolean literal not 0 or 1\n");
1543#endif
1544 return false;
1545 }
1546 return Parse('E');
1547 }
1548
1549 // <expr-primary> ::= L <type> <value number> E #
1550 // integer literal
1551 // ::= L <type> <value float> E #
1552 // floating literal
1553 // ::= L <string type> E #
1554 // string literal
1555 // ::= L <nullptr type> E #
1556 // nullptr literal (i.e., "LDnE")
1557 // ::= L <type> <real-part float> _ <imag-part float> E #
1558 // complex floating point literal (C 2000)
1559 // ::= L <mangled-name> E #
1560 // external name
1561
1562 bool ParseExpressionPrimary() {
1563 switch (*m_read_ptr++) {
1564 case 'b':
1565 return ParseBooleanLiteral();
1566 case 'x':
1567 return ParseIntegerLiteral(nullptr, "ll", true);
1568 case 'l':
1569 return ParseIntegerLiteral(nullptr, "l", true);
1570 case 'i':
1571 return ParseIntegerLiteral(nullptr, nullptr, true);
1572 case 'n':
1573 return ParseIntegerLiteral("(__int128)", nullptr, true);
1574 case 'j':
1575 return ParseIntegerLiteral(nullptr, "u", false);
1576 case 'm':
1577 return ParseIntegerLiteral(nullptr, "ul", false);
1578 case 'y':
1579 return ParseIntegerLiteral(nullptr, "ull", false);
1580 case 'o':
1581 return ParseIntegerLiteral("(unsigned __int128)", nullptr, false);
1582 case '_':
1583 if (*m_read_ptr++ == 'Z') {
1584 if (!ParseEncoding())
1585 return false;
1586 return Parse('E');
1587 }
1588 --m_read_ptr;
1589 LLVM_FALLTHROUGH[[clang::fallthrough]];
1590 case 'w':
1591 case 'c':
1592 case 'a':
1593 case 'h':
1594 case 's':
1595 case 't':
1596 case 'f':
1597 case 'd':
1598 case 'e':
1599#ifdef DEBUG_FAILURES
1600 printf("*** Unsupported primary expression %.5s\n", m_read_ptr - 1);
1601#endif
1602 return false;
1603 case 'T':
1604// Invalid mangled name per
1605// http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
1606#ifdef DEBUG_FAILURES
1607 printf("*** Invalid primary expr encoding\n");
1608#endif
1609 return false;
1610 default:
1611 --m_read_ptr;
1612 Write('(');
1613 if (!ParseType())
1614 return false;
1615 Write(')');
1616 if (!ParseNumber())
1617 return false;
1618 return Parse('E');
1619 }
1620 }
1621
1622 // <unresolved-type> ::= <template-param>
1623 // ::= <decltype>
1624 // ::= <substitution>
1625
1626 bool ParseUnresolvedType() {
1627 int type_start_cookie = GetStartCookie();
1628 switch (*m_read_ptr++) {
1
Control jumps to 'case 83:' at line 1634
1629 case 'T':
1630 if (!ParseTemplateParam())
1631 return false;
1632 EndSubstitution(type_start_cookie);
1633 return true;
1634 case 'S': {
1635 if (*m_read_ptr != 't')
2
Assuming the condition is false
3
Taking false branch
1636 return ParseSubstitution();
1637
1638 ++m_read_ptr;
1639 WriteStdPrefix();
1640 NameState type_name = {};
1641 if (!ParseUnqualifiedName(type_name))
4
Calling 'SymbolDemangler::ParseUnqualifiedName'
1642 return false;
1643 EndSubstitution(type_start_cookie);
1644 return true;
1645 }
1646 case 'D':
1647 default:
1648#ifdef DEBUG_FAILURES
1649 printf("*** Unsupported unqualified type: %3s\n", m_read_ptr - 1);
1650#endif
1651 return false;
1652 }
1653 }
1654
1655 // <base-unresolved-name> ::= <simple-id> #
1656 // unresolved name
1657 // extension ::= <operator-name> #
1658 // unresolved operator-function-id
1659 // extension ::= <operator-name> <template-args> #
1660 // unresolved operator template-id
1661 // ::= on <operator-name> #
1662 // unresolved operator-function-id
1663 // ::= on <operator-name> <template-args> #
1664 // unresolved operator template-id
1665 // ::= dn <destructor-name> #
1666 // destructor or pseudo-destructor;
1667 // #
1668 // e.g.
1669 // ~X
1670 // or
1671 // ~X<N-1>
1672
1673 bool ParseBaseUnresolvedName() {
1674#ifdef DEBUG_FAILURES
1675 printf("*** Base unresolved name unsupported\n");
1676#endif
1677 return false;
1678 }
1679
1680 // <unresolved-name>
1681 // extension ::= srN <unresolved-type> [<template-args>]
1682 // <unresolved-qualifier-level>* E <base-unresolved-name>
1683 // ::= [gs] <base-unresolved-name> # x
1684 // or (with "gs") ::x
1685 // ::= [gs] sr <unresolved-qualifier-level>+ E
1686 // <base-unresolved-name>
1687 // #
1688 // A::x,
1689 // N::y,
1690 // A<T>::z;
1691 // "gs"
1692 // means
1693 // leading
1694 // "::"
1695 // ::= sr <unresolved-type> <base-unresolved-name> #
1696 // T::x / decltype(p)::x
1697 // extension ::= sr <unresolved-type> <template-args>
1698 // <base-unresolved-name>
1699 // #
1700 // T::N::x
1701 // /decltype(p)::N::x
1702 // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+
1703 // E <base-unresolved-name>
1704
1705 bool ParseUnresolvedName() {
1706#ifdef DEBUG_FAILURES
1707 printf("*** Unresolved names not supported\n");
1708#endif
1709 // TODO: grammar for all of this seems unclear...
1710 return false;
1711
1712#if 0 // TODO
1713 if (*m_read_ptr == 'g' && *(m_read_ptr + 1) == 's')
1714 {
1715 m_read_ptr += 2;
1716 WriteNamespaceSeparator();
1717 }
1718#endif // TODO
1719 }
1720
1721 // <expression> ::= <unary operator-name> <expression>
1722 // ::= <binary operator-name> <expression> <expression>
1723 // ::= <ternary operator-name> <expression> <expression>
1724 // <expression>
1725 // ::= cl <expression>+ E #
1726 // call
1727 // ::= cv <type> <expression> #
1728 // conversion with one argument
1729 // ::= cv <type> _ <expression>* E #
1730 // conversion with a different number of arguments
1731 // ::= [gs] nw <expression>* _ <type> E # new
1732 // (expr-list) type
1733 // ::= [gs] nw <expression>* _ <type> <initializer> # new
1734 // (expr-list) type (init)
1735 // ::= [gs] na <expression>* _ <type> E #
1736 // new[] (expr-list) type
1737 // ::= [gs] na <expression>* _ <type> <initializer> #
1738 // new[] (expr-list) type (init)
1739 // ::= [gs] dl <expression> #
1740 // delete expression
1741 // ::= [gs] da <expression> #
1742 // delete[] expression
1743 // ::= pp_ <expression> #
1744 // prefix ++
1745 // ::= mm_ <expression> #
1746 // prefix --
1747 // ::= ti <type> #
1748 // typeid (type)
1749 // ::= te <expression> #
1750 // typeid (expression)
1751 // ::= dc <type> <expression> #
1752 // dynamic_cast<type> (expression)
1753 // ::= sc <type> <expression> #
1754 // static_cast<type> (expression)
1755 // ::= cc <type> <expression> #
1756 // const_cast<type> (expression)
1757 // ::= rc <type> <expression> #
1758 // reinterpret_cast<type> (expression)
1759 // ::= st <type> #
1760 // sizeof (a type)
1761 // ::= sz <expression> #
1762 // sizeof (an expression)
1763 // ::= at <type> #
1764 // alignof (a type)
1765 // ::= az <expression> #
1766 // alignof (an expression)
1767 // ::= nx <expression> #
1768 // noexcept (expression)
1769 // ::= <template-param>
1770 // ::= <function-param>
1771 // ::= dt <expression> <unresolved-name> #
1772 // expr.name
1773 // ::= pt <expression> <unresolved-name> #
1774 // expr->name
1775 // ::= ds <expression> <expression> #
1776 // expr.*expr
1777 // ::= sZ <template-param> #
1778 // size of a parameter pack
1779 // ::= sZ <function-param> #
1780 // size of a function parameter pack
1781 // ::= sp <expression> #
1782 // pack expansion
1783 // ::= tw <expression> #
1784 // throw expression
1785 // ::= tr #
1786 // throw with no operand (rethrow)
1787 // ::= <unresolved-name> #
1788 // f(p), N::f(p), ::f(p),
1789 // #
1790 // freestanding
1791 // dependent
1792 // name
1793 // (e.g.,
1794 // T::x),
1795 // #
1796 // objectless
1797 // nonstatic
1798 // member
1799 // reference
1800 // ::= <expr-primary>
1801
1802 bool ParseExpression() {
1803 Operator expression_operator = TryParseOperator();
1804 switch (expression_operator.kind) {
1805 case OperatorKind::Unary:
1806 Write(expression_operator.name);
1807 Write('(');
1808 if (!ParseExpression())
1809 return false;
1810 Write(')');
1811 return true;
1812 case OperatorKind::Binary:
1813 if (!ParseExpression())
1814 return false;
1815 Write(expression_operator.name);
1816 return ParseExpression();
1817 case OperatorKind::Ternary:
1818 if (!ParseExpression())
1819 return false;
1820 Write('?');
1821 if (!ParseExpression())
1822 return false;
1823 Write(':');
1824 return ParseExpression();
1825 case OperatorKind::NoMatch:
1826 break;
1827 case OperatorKind::Other:
1828 default:
1829#ifdef DEBUG_FAILURES
1830 printf("*** Unsupported operator: %s\n", expression_operator.name);
1831#endif
1832 return false;
1833 }
1834
1835 switch (*m_read_ptr++) {
1836 case 'T':
1837 return ParseTemplateParam();
1838 case 'L':
1839 return ParseExpressionPrimary();
1840 case 's':
1841 if (*m_read_ptr++ == 'r')
1842 return ParseUnresolvedName();
1843 --m_read_ptr;
1844 LLVM_FALLTHROUGH[[clang::fallthrough]];
1845 default:
1846 return ParseExpressionPrimary();
1847 }
1848 }
1849
1850 // <template-arg> ::= <type> #
1851 // type or template
1852 // ::= X <expression> E #
1853 // expression
1854 // ::= <expr-primary> #
1855 // simple expressions
1856 // ::= J <template-arg>* E #
1857 // argument pack
1858 // ::= LZ <encoding> E #
1859 // extension
1860
1861 bool ParseTemplateArg() {
1862 switch (*m_read_ptr) {
1863 case 'J':
1864#ifdef DEBUG_FAILURES
1865 printf("*** Template argument packs unsupported\n");
1866#endif
1867 return false;
1868 case 'X':
1869 ++m_read_ptr;
1870 if (!ParseExpression())
1871 return false;
1872 return Parse('E');
1873 case 'L':
1874 ++m_read_ptr;
1875 return ParseExpressionPrimary();
1876 default:
1877 return ParseType();
1878 }
1879 }
1880
1881 // <template-args> ::= I <template-arg>* E
1882 // extension, the abi says <template-arg>+
1883
1884 bool ParseTemplateArgs(bool record_template_args = false) {
1885 if (record_template_args)
1886 ResetTemplateArgs();
1887
1888 bool first_arg = true;
1889 while (*m_read_ptr != 'E') {
1890 if (first_arg)
1891 first_arg = false;
1892 else
1893 WriteCommaSpace();
1894
1895 int template_start_cookie = GetStartCookie();
1896 if (!ParseTemplateArg())
1897 return false;
1898 if (record_template_args)
1899 EndTemplateArg(template_start_cookie);
1900 }
1901 ++m_read_ptr;
1902 return true;
1903 }
1904
1905 // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix>
1906 // <unqualified-name> E
1907 // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix>
1908 // <template-args> E
1909 //
1910 // <prefix> ::= <prefix> <unqualified-name>
1911 // ::= <template-prefix> <template-args>
1912 // ::= <template-param>
1913 // ::= <decltype>
1914 // ::= # empty
1915 // ::= <substitution>
1916 // ::= <prefix> <data-member-prefix>
1917 // extension ::= L
1918 //
1919 // <template-prefix> ::= <prefix> <template unqualified-name>
1920 // ::= <template-param>
1921 // ::= <substitution>
1922 //
1923 // <unqualified-name> ::= <operator-name>
1924 // ::= <ctor-dtor-name>
1925 // ::= <source-name>
1926 // ::= <unnamed-type-name>
1927
1928 bool ParseNestedName(NameState &name_state,
1929 bool parse_discriminator = false) {
1930 int qualifiers = TryParseQualifiers(true, true);
1931 bool first_part = true;
1932 bool suppress_substitution = true;
1933 int name_start_cookie = GetStartCookie();
1934 while (true) {
1935 char next = *m_read_ptr;
1936 if (next == 'E') {
1937 ++m_read_ptr;
1938 break;
1939 }
1940
1941 // Record a substitution candidate for all prefixes, but not the full
1942 // name
1943 if (suppress_substitution)
1944 suppress_substitution = false;
1945 else
1946 EndSubstitution(name_start_cookie);
1947
1948 if (next == 'I') {
1949 ++m_read_ptr;
1950 name_state.is_last_generic = true;
1951 WriteTemplateStart();
1952 if (!ParseTemplateArgs(name_state.parse_function_params))
1953 return false;
1954 WriteTemplateEnd();
1955 continue;
1956 }
1957
1958 if (first_part)
1959 first_part = false;
1960 else
1961 WriteNamespaceSeparator();
1962
1963 name_state.is_last_generic = false;
1964 switch (next) {
1965 case '0':
1966 case '1':
1967 case '2':
1968 case '3':
1969 case '4':
1970 case '5':
1971 case '6':
1972 case '7':
1973 case '8':
1974 case '9': {
1975 int name_start_cookie = GetStartCookie();
1976 if (!ParseSourceName())
1977 return false;
1978 name_state.last_name_range = EndRange(name_start_cookie);
1979 continue;
1980 }
1981 case 'S':
1982 if (*++m_read_ptr == 't') {
1983 WriteStdPrefix();
1984 ++m_read_ptr;
1985 if (!ParseUnqualifiedName(name_state))
1986 return false;
1987 } else {
1988 if (!ParseSubstitution())
1989 return false;
1990 suppress_substitution = true;
1991 }
1992 continue;
1993 case 'T':
1994 ++m_read_ptr;
1995 if (!ParseTemplateParam())
1996 return false;
1997 continue;
1998 case 'C':
1999 ++m_read_ptr;
2000 if (!ParseCtor(name_state))
2001 return false;
2002 continue;
2003 case 'D': {
2004 switch (*(m_read_ptr + 1)) {
2005 case 't':
2006 case 'T':
2007#ifdef DEBUG_FAILURES
2008 printf("*** Decltype unsupported\n");
2009#endif
2010 return false;
2011 }
2012 ++m_read_ptr;
2013 if (!ParseDtor(name_state))
2014 return false;
2015 continue;
2016 }
2017 case 'U':
2018 ++m_read_ptr;
2019 if (!ParseUnnamedTypeName(name_state))
2020 return false;
2021 continue;
2022 case 'L':
2023 ++m_read_ptr;
2024 if (!ParseUnqualifiedName(name_state))
2025 return false;
2026 continue;
2027 default:
2028 if (!ParseOperatorName(name_state))
2029 return false;
2030 }
2031 }
2032
2033 if (parse_discriminator)
2034 TryParseDiscriminator();
2035 if (name_state.parse_function_params &&
2036 !ParseFunctionArgs(name_state, name_start_cookie)) {
2037 return false;
2038 }
2039 if (qualifiers)
2040 WriteQualifiers(qualifiers);
2041 return true;
2042 }
2043
2044 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2045 // := Z <function encoding> E s [<discriminator>]
2046 // := Z <function encoding> Ed [ <parameter number> ] _ <entity
2047 // name>
2048
2049 bool ParseLocalName(bool parse_function_params) {
2050 if (!ParseEncoding())
2051 return false;
2052 if (!Parse('E'))
2053 return false;
2054
2055 switch (*m_read_ptr) {
2056 case 's':
2057 ++m_read_ptr;
2058 TryParseDiscriminator(); // Optional and ignored
2059 WRITE("::string literal")Write("::string literal", sizeof("::string literal") - 1);
2060 break;
2061 case 'd':
2062 ++m_read_ptr;
2063 TryParseNumber(); // Optional and ignored
2064 if (!Parse('_'))
2065 return false;
2066 WriteNamespaceSeparator();
2067 if (!ParseName())
2068 return false;
2069 break;
2070 default:
2071 WriteNamespaceSeparator();
2072 if (!ParseName(parse_function_params, true))
2073 return false;
2074 TryParseDiscriminator(); // Optional and ignored
2075 }
2076 return true;
2077 }
2078
2079 // <name> ::= <nested-name>
2080 // ::= <local-name>
2081 // ::= <unscoped-template-name> <template-args>
2082 // ::= <unscoped-name>
2083
2084 // <unscoped-template-name> ::= <unscoped-name>
2085 // ::= <substitution>
2086
2087 bool ParseName(bool parse_function_params = false,
2088 bool parse_discriminator = false) {
2089 NameState name_state = {parse_function_params, false, false, {0, 0}};
2090 int name_start_cookie = GetStartCookie();
2091
2092 switch (*m_read_ptr) {
2093 case 'N':
2094 ++m_read_ptr;
2095 return ParseNestedName(name_state, parse_discriminator);
2096 case 'Z': {
2097 ++m_read_ptr;
2098 if (!ParseLocalName(parse_function_params))
2099 return false;
2100 break;
2101 }
2102 case 'L':
2103 ++m_read_ptr;
2104 LLVM_FALLTHROUGH[[clang::fallthrough]];
2105 default: {
2106 if (!ParseUnscopedName(name_state))
2107 return false;
2108
2109 if (*m_read_ptr == 'I') {
2110 EndSubstitution(name_start_cookie);
2111
2112 ++m_read_ptr;
2113 name_state.is_last_generic = true;
2114 WriteTemplateStart();
2115 if (!ParseTemplateArgs(parse_function_params))
2116 return false;
2117 WriteTemplateEnd();
2118 }
2119 break;
2120 }
2121 }
2122 if (parse_discriminator)
2123 TryParseDiscriminator();
2124 if (parse_function_params &&
2125 !ParseFunctionArgs(name_state, name_start_cookie)) {
2126 return false;
2127 }
2128 return true;
2129 }
2130
2131 // <call-offset> ::= h <nv-offset> _
2132 // ::= v <v-offset> _
2133 //
2134 // <nv-offset> ::= <offset number>
2135 // # non-virtual base override
2136 //
2137 // <v-offset> ::= <offset number> _ <virtual offset number>
2138 // # virtual base override, with vcall offset
2139
2140 bool ParseCallOffset() {
2141 switch (*m_read_ptr++) {
2142 case 'h':
2143 if (*m_read_ptr == 'n')
2144 ++m_read_ptr;
2145 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2146 break;
2147 return true;
2148 case 'v':
2149 if (*m_read_ptr == 'n')
2150 ++m_read_ptr;
2151 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2152 break;
2153 if (*m_read_ptr == 'n')
2154 ++m_read_ptr;
2155 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2156 break;
2157 return true;
2158 }
2159#ifdef DEBUG_FAILURES
2160 printf("*** Malformed call offset\n");
2161#endif
2162 return false;
2163 }
2164
2165 // <special-name> ::= TV <type> # virtual table
2166 // ::= TT <type> # VTT structure (construction vtable index)
2167 // ::= TI <type> # typeinfo structure
2168 // ::= TS <type> # typeinfo name (null-terminated byte
2169 // string)
2170 // ::= Tc <call-offset> <call-offset> <base encoding>
2171 // # base is the nominal target function of thunk
2172 // # first call-offset is 'this' adjustment
2173 // # second call-offset is result adjustment
2174 // ::= T <call-offset> <base encoding>
2175 // # base is the nominal target function of thunk
2176 // extension ::= TC <first type> <number> _ <second type> # construction
2177 // vtable for second-in-first
2178
2179 bool ParseSpecialNameT() {
2180 switch (*m_read_ptr++) {
2181 case 'V':
2182 WRITE("vtable for ")Write("vtable for ", sizeof("vtable for ") - 1);
2183 return ParseType();
2184 case 'T':
2185 WRITE("VTT for ")Write("VTT for ", sizeof("VTT for ") - 1);
2186 return ParseType();
2187 case 'I':
2188 WRITE("typeinfo for ")Write("typeinfo for ", sizeof("typeinfo for ") - 1);
2189 return ParseType();
2190 case 'S':
2191 WRITE("typeinfo name for ")Write("typeinfo name for ", sizeof("typeinfo name for ") - 1);
2192 return ParseType();
2193 case 'c':
2194 case 'C':
2195#ifdef DEBUG_FAILURES
2196 printf("*** Unsupported thunk or construction vtable name: %.3s\n",
2197 m_read_ptr - 1);
2198#endif
2199 return false;
2200 default:
2201 if (*--m_read_ptr == 'v') {
2202 WRITE("virtual thunk to ")Write("virtual thunk to ", sizeof("virtual thunk to ") - 1);
2203 } else {
2204 WRITE("non-virtual thunk to ")Write("non-virtual thunk to ", sizeof("non-virtual thunk to "
) - 1)
;
2205 }
2206 if (!ParseCallOffset())
2207 return false;
2208 return ParseEncoding();
2209 }
2210 }
2211
2212 // <special-name> ::= GV <object name> # Guard variable for one-time
2213 // initialization
2214 // # No <type>
2215 // extension ::= GR <object name> # reference temporary for object
2216
2217 bool ParseSpecialNameG() {
2218 switch (*m_read_ptr++) {
2219 case 'V':
2220 WRITE("guard variable for ")Write("guard variable for ", sizeof("guard variable for ") - 1
)
;
2221 if (!ParseName(true))
2222 return false;
2223 break;
2224 case 'R':
2225 WRITE("reference temporary for ")Write("reference temporary for ", sizeof("reference temporary for "
) - 1)
;
2226 if (!ParseName(true))
2227 return false;
2228 break;
2229 default:
2230#ifdef DEBUG_FAILURES
2231 printf("*** Unknown G encoding\n");
2232#endif
2233 return false;
2234 }
2235 return true;
2236 }
2237
2238 // <bare-function-type> ::= <signature type>+ # types are possible
2239 // return type, then parameter types
2240
2241 bool ParseFunctionArgs(NameState &name_state, int return_insert_cookie) {
2242 char next = *m_read_ptr;
2243 if (next == 'E' || next == '\0' || next == '.')
2244 return true;
2245
2246 // Clang has a bad habit of making unique manglings by just sticking
2247 // numbers on the end of a symbol, which is ambiguous with malformed source
2248 // name manglings
2249 const char *before_clang_uniquing_test = m_read_ptr;
2250 if (TryParseNumber()) {
2251 if (*m_read_ptr == '\0')
2252 return true;
2253 m_read_ptr = before_clang_uniquing_test;
2254 }
2255
2256 if (name_state.is_last_generic && !name_state.has_no_return_type) {
2257 int return_type_start_cookie = GetStartCookie();
2258 if (!ParseType())
2259 return false;
2260 Write(' ');
2261 ReorderRange(EndRange(return_type_start_cookie), return_insert_cookie);
2262 }
2263
2264 Write('(');
2265 bool first_param = true;
2266 while (true) {
2267 switch (*m_read_ptr) {
2268 case '\0':
2269 case 'E':
2270 case '.':
2271 break;
2272 case 'v':
2273 ++m_read_ptr;
2274 continue;
2275 case '_':
2276 // Not a formal part of the mangling specification, but clang emits
2277 // suffixes starting with _block_invoke
2278 if (strncmp(m_read_ptr, "_block_invoke", 13) == 0) {
2279 m_read_ptr += strlen(m_read_ptr);
2280 break;
2281 }
2282 LLVM_FALLTHROUGH[[clang::fallthrough]];
2283 default:
2284 if (first_param)
2285 first_param = false;
2286 else
2287 WriteCommaSpace();
2288
2289 if (!ParseType())
2290 return false;
2291 continue;
2292 }
2293 break;
2294 }
2295 Write(')');
2296 return true;
2297 }
2298
2299 // <encoding> ::= <function name> <bare-function-type>
2300 // ::= <data name>
2301 // ::= <special-name>
2302
2303 bool ParseEncoding() {
2304 switch (*m_read_ptr) {
2305 case 'T':
2306 ++m_read_ptr;
2307 if (!ParseSpecialNameT())
2308 return false;
2309 break;
2310 case 'G':
2311 ++m_read_ptr;
2312 if (!ParseSpecialNameG())
2313 return false;
2314 break;
2315 default:
2316 if (!ParseName(true))
2317 return false;
2318 break;
2319 }
2320 return true;
2321 }
2322
2323 bool ParseMangling(const char *mangled_name, long mangled_name_length = 0) {
2324 if (!mangled_name_length)
2325 mangled_name_length = strlen(mangled_name);
2326 m_read_end = mangled_name + mangled_name_length;
2327 m_read_ptr = mangled_name;
2328 m_write_ptr = m_buffer;
2329 m_next_substitute_index = 0;
2330 m_next_template_arg_index = m_rewrite_ranges_size - 1;
2331
2332 if (*m_read_ptr++ != '_' || *m_read_ptr++ != 'Z') {
2333#ifdef DEBUG_FAILURES
2334 printf("*** Missing _Z prefix\n");
2335#endif
2336 return false;
2337 }
2338 if (!ParseEncoding())
2339 return false;
2340 switch (*m_read_ptr) {
2341 case '.':
2342 Write(' ');
2343 Write('(');
2344 Write(m_read_ptr, m_read_end - m_read_ptr);
2345 Write(')');
2346 LLVM_FALLTHROUGH[[clang::fallthrough]];
2347 case '\0':
2348 return true;
2349 default:
2350#ifdef DEBUG_FAILURES
2351 printf("*** Unparsed mangled content\n");
2352#endif
2353 return false;
2354 }
2355 }
2356
2357private:
2358 // External scratch storage used during demanglings
2359
2360 char *m_buffer;
2361 const char *m_buffer_end;
2362 BufferRange *m_rewrite_ranges;
2363 int m_rewrite_ranges_size;
2364 bool m_owns_buffer;
2365 bool m_owns_m_rewrite_ranges;
2366
2367 // Internal state used during demangling
2368
2369 const char *m_read_ptr;
2370 const char *m_read_end;
2371 char *m_write_ptr;
2372 int m_next_template_arg_index;
2373 int m_next_substitute_index;
2374 std::function<void(const char *s)> m_builtins_hook;
2375};
2376
2377} // Anonymous namespace
2378
2379// Public entry points referenced from Mangled.cpp
2380namespace lldb_private {
2381char *FastDemangle(const char *mangled_name) {
2382 char buffer[16384];
2383 SymbolDemangler demangler(buffer, sizeof(buffer));
2384 return demangler.GetDemangledCopy(mangled_name);
2385}
2386
2387char *FastDemangle(const char *mangled_name, size_t mangled_name_length,
2388 std::function<void(const char *s)> builtins_hook) {
2389 char buffer[16384];
2390 SymbolDemangler demangler(buffer, sizeof(buffer), builtins_hook);
2391 return demangler.GetDemangledCopy(mangled_name, mangled_name_length);
2392}
2393} // lldb_private namespace