blob: 0f12af2783db63cc97b0d11ca6eed9f048851a38 [file] [log] [blame]
Kate Stonee2b21862014-07-22 17:03:38 +00001//===-- 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 <stdio.h>
11#include <string.h>
12#include <stdlib.h>
13
14//#define DEBUG_FAILURES 1
15//#define DEBUG_SUBSTITUTIONS 1
16//#define DEBUG_TEMPLATE_ARGS 1
17//#define DEBUG_HIGHWATER 1
18//#define DEBUG_REORDERING 1
19
20namespace {
Jason Molenda026aa492014-10-15 22:11:15 +000021
Kate Stonee2b21862014-07-22 17:03:38 +000022/// @brief Represents the collection of qualifiers on a type
23
24enum Qualifiers
25{
26 QualifierNone = 0,
27 QualifierConst = 1,
28 QualifierRestrict = 2,
29 QualifierVolatile = 4,
30 QualifierReference = 8,
31 QualifierRValueReference = 16,
32 QualifierPointer = 32
33};
34
35/// @brief Categorizes the recognized operators
36
37enum class OperatorKind
38{
39 Unary,
40 Postfix,
41 Binary,
42 Ternary,
43 Other,
44 ConversionOperator,
45 Vendor,
46 NoMatch
47};
48
49/// @brief Represents one of the recognized two-character operator
50/// abbreviations used when parsing operators as names and expressions
51
52struct Operator
53{
Jason Molenda026aa492014-10-15 22:11:15 +000054 const char *name;
Kate Stonee2b21862014-07-22 17:03:38 +000055 OperatorKind kind;
56};
57
58/// @brief Represents a range of characters in the output buffer, typically for
59/// use with RewriteRange()
60
61struct BufferRange
62{
63 int offset;
64 int length;
65};
66
67/// @brief Transient state required while parsing a name
68
69struct NameState
70{
71 bool parse_function_params;
72 bool is_last_generic;
73 bool has_no_return_type;
74 BufferRange last_name_range;
75};
76
77/// @brief LLDB's fast C++ demangler
78///
79/// This is an incomplete implementation designed to speed up the demangling
80/// process that is often a bottleneck when LLDB stops a process for the first
81/// time. Where the implementation doesn't know how to demangle a symbol it
82/// fails gracefully to allow the caller to fall back to the existing demangler.
83///
84/// Over time the full mangling spec should be supported without compromising
85/// performance for the most common cases.
86
87class SymbolDemangler
88{
89public:
Jason Molenda026aa492014-10-15 22:11:15 +000090
Kate Stonee2b21862014-07-22 17:03:38 +000091 //----------------------------------------------------
92 // Public API
93 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +000094
Kate Stonee2b21862014-07-22 17:03:38 +000095 /// @brief 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.
Jason Molenda026aa492014-10-15 22:11:15 +0000100
Kate Stonee2b21862014-07-22 17:03:38 +0000101 SymbolDemangler()
102 {
Jason Molenda026aa492014-10-15 22:11:15 +0000103 m_buffer = (char *) malloc(8192);
104 m_buffer_end = m_buffer + 8192;
105 m_owns_buffer = true;
106
107 m_rewrite_ranges = (BufferRange *) malloc(128 * sizeof (BufferRange));
108 m_rewrite_ranges_size = 128;
109 m_owns_m_rewrite_ranges = true;
Kate Stonee2b21862014-07-22 17:03:38 +0000110 }
Jason Molenda026aa492014-10-15 22:11:15 +0000111
Kate Stonee2b21862014-07-22 17:03:38 +0000112 /// @brief Create a SymbolDemangler that uses provided scratch memory
113 ///
114 /// The provided memory is not owned by the demangler. It will be
115 /// overwritten during calls to GetDemangledCopy() but can be used for
116 /// other purposes between calls. The provided memory will not be freed
117 /// when this instance is destroyed.
118 ///
119 /// If demangling a symbol requires additional space it will be allocated
120 /// and managed by the demangler instance.
121 ///
122 /// @param storage_ptr Valid pointer to at least storage_size bytes of
123 /// space that the SymbolDemangler can use during demangling
124 ///
125 /// @param storage_size Number of bytes of space available scratch memory
126 /// referenced by storage_ptr
Jason Molenda026aa492014-10-15 22:11:15 +0000127
128 SymbolDemangler(void *storage_ptr, int storage_size)
Kate Stonee2b21862014-07-22 17:03:38 +0000129 {
130 // Use up to 1/8th of the provided space for rewrite ranges
Jason Molenda026aa492014-10-15 22:11:15 +0000131 m_rewrite_ranges_size = (storage_size >> 3) / sizeof (BufferRange);
132 m_rewrite_ranges = (BufferRange *) storage_ptr;
133 m_owns_m_rewrite_ranges = false;
134
Kate Stonee2b21862014-07-22 17:03:38 +0000135 // Use the rest for the character buffer
Jason Molenda026aa492014-10-15 22:11:15 +0000136 m_buffer = (char *) storage_ptr + m_rewrite_ranges_size * sizeof (BufferRange);
137 m_buffer_end = (const char *)storage_ptr + storage_size;
138 m_owns_buffer = false;
Kate Stonee2b21862014-07-22 17:03:38 +0000139 }
Jason Molenda026aa492014-10-15 22:11:15 +0000140
Kate Stonee2b21862014-07-22 17:03:38 +0000141 /// @brief Destroys the SymbolDemangler and deallocates any scratch
142 /// memory that it owns
Jason Molenda026aa492014-10-15 22:11:15 +0000143
Kate Stonee2b21862014-07-22 17:03:38 +0000144 ~SymbolDemangler()
145 {
Jason Molenda026aa492014-10-15 22:11:15 +0000146 if (m_owns_buffer)
147 free(m_buffer);
148 if (m_owns_m_rewrite_ranges)
149 free(m_rewrite_ranges);
Kate Stonee2b21862014-07-22 17:03:38 +0000150 }
Jason Molenda026aa492014-10-15 22:11:15 +0000151
Kate Stonee2b21862014-07-22 17:03:38 +0000152#ifdef DEBUG_HIGHWATER
153 int highwater_store = 0;
154 int highwater_buffer = 0;
155#endif
Jason Molenda026aa492014-10-15 22:11:15 +0000156
Kate Stonee2b21862014-07-22 17:03:38 +0000157 /// @brief Parses the provided mangled name and returns a newly allocated
158 /// demangling
159 ///
160 /// @param mangled_name Valid null-terminated C++ mangled name following
161 /// the Itanium C++ ABI mangling specification as implemented by Clang
162 ///
163 /// @result Newly allocated null-terminated demangled name when demangling
164 /// is succesful, and nullptr when demangling fails. The caller is
165 /// responsible for freeing the allocated memory.
Jason Molenda026aa492014-10-15 22:11:15 +0000166
167 char *
168 GetDemangledCopy(const char *mangled_name,
169 long mangled_name_length = 0)
Kate Stonee2b21862014-07-22 17:03:38 +0000170 {
Jason Molenda026aa492014-10-15 22:11:15 +0000171 if (!ParseMangling(mangled_name, mangled_name_length))
172 return nullptr;
173
Kate Stonee2b21862014-07-22 17:03:38 +0000174#ifdef DEBUG_HIGHWATER
Jason Molenda026aa492014-10-15 22:11:15 +0000175 int rewrite_count = m_next_substitute_index +
176 (m_rewrite_ranges_size - 1 - m_next_template_arg_index);
177 int buffer_size = (int)(m_write_ptr - m_buffer);
178 if (rewrite_count > highwater_store)
179 highwater_store = rewrite_count;
180 if (buffer_size > highwater_buffer)
181 highwater_buffer = buffer_size;
Kate Stonee2b21862014-07-22 17:03:38 +0000182#endif
Jason Molenda026aa492014-10-15 22:11:15 +0000183
184 int length = (int)(m_write_ptr - m_buffer);
185 char *copy = (char *)malloc(length + 1);
186 memcpy(copy, m_buffer, length);
Kate Stonee2b21862014-07-22 17:03:38 +0000187 copy[length] = '\0';
188 return copy;
189 }
Jason Molenda026aa492014-10-15 22:11:15 +0000190
Kate Stonee2b21862014-07-22 17:03:38 +0000191private:
Jason Molenda026aa492014-10-15 22:11:15 +0000192
Kate Stonee2b21862014-07-22 17:03:38 +0000193 //----------------------------------------------------
194 // Grow methods
195 //
196 // Manage the storage used during demangling
197 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000198
Kate Stonee2b21862014-07-22 17:03:38 +0000199 void GrowBuffer(long min_growth = 0)
200 {
201 // By default, double the size of the buffer
Jason Molenda026aa492014-10-15 22:11:15 +0000202 long growth = m_buffer_end - m_buffer;
203
Kate Stonee2b21862014-07-22 17:03:38 +0000204 // Avoid growing by more than 1MB at a time
Jason Molenda026aa492014-10-15 22:11:15 +0000205 if (growth > 1 << 20)
206 growth = 1 << 20;
207
Kate Stonee2b21862014-07-22 17:03:38 +0000208 // ... but never grow by less than requested,
209 // or 1K, whichever is greater
Jason Molenda026aa492014-10-15 22:11:15 +0000210 if (min_growth < 1024)
211 min_growth = 1024;
212 if (growth < min_growth)
213 growth = min_growth;
214
215 // Allocate the new m_buffer and migrate content
216 long new_size = (m_buffer_end - m_buffer) + growth;
217 char *new_buffer = (char *) malloc(new_size);
218 memcpy(new_buffer, m_buffer, m_write_ptr - m_buffer);
219 if (m_owns_buffer)
220 free(m_buffer);
221 m_owns_buffer = true;
222
Kate Stonee2b21862014-07-22 17:03:38 +0000223 // Update references to the new buffer
Jason Molenda026aa492014-10-15 22:11:15 +0000224 m_write_ptr = new_buffer + (m_write_ptr - m_buffer);
225 m_buffer = new_buffer;
226 m_buffer_end = m_buffer + new_size;
Kate Stonee2b21862014-07-22 17:03:38 +0000227 }
Jason Molenda026aa492014-10-15 22:11:15 +0000228
229 void
230 GrowRewriteRanges()
Kate Stonee2b21862014-07-22 17:03:38 +0000231 {
232 // By default, double the size of the array
Jason Molenda026aa492014-10-15 22:11:15 +0000233 int growth = m_rewrite_ranges_size;
234
Kate Stonee2b21862014-07-22 17:03:38 +0000235 // Apply reasonable minimum and maximum sizes for growth
Jason Molenda026aa492014-10-15 22:11:15 +0000236 if (growth > 128)
237 growth = 128;
238 if (growth < 16)
239 growth = 16;
240
Kate Stonee2b21862014-07-22 17:03:38 +0000241 // Allocate the new array and migrate content
Jason Molenda026aa492014-10-15 22:11:15 +0000242 int bytes = (m_rewrite_ranges_size + growth) * sizeof (BufferRange);
243 BufferRange *new_ranges = (BufferRange *) malloc (bytes);
244 for (int index = 0; index < m_next_substitute_index; index++)
Kate Stonee2b21862014-07-22 17:03:38 +0000245 {
Jason Molenda026aa492014-10-15 22:11:15 +0000246 new_ranges[index] = m_rewrite_ranges[index];
Kate Stonee2b21862014-07-22 17:03:38 +0000247 }
Jason Molenda026aa492014-10-15 22:11:15 +0000248 for (int index = m_rewrite_ranges_size - 1;
249 index > m_next_template_arg_index; index--)
Kate Stonee2b21862014-07-22 17:03:38 +0000250 {
Jason Molenda026aa492014-10-15 22:11:15 +0000251 new_ranges[index + growth] = m_rewrite_ranges[index];
Kate Stonee2b21862014-07-22 17:03:38 +0000252 }
Jason Molenda026aa492014-10-15 22:11:15 +0000253 if (m_owns_m_rewrite_ranges)
254 free(m_rewrite_ranges);
255 m_owns_m_rewrite_ranges = true;
256
Kate Stonee2b21862014-07-22 17:03:38 +0000257 // Update references to the new array
Jason Molenda026aa492014-10-15 22:11:15 +0000258 m_rewrite_ranges = new_ranges;
259 m_rewrite_ranges_size += growth;
260 m_next_template_arg_index += growth;
Kate Stonee2b21862014-07-22 17:03:38 +0000261 }
Jason Molenda026aa492014-10-15 22:11:15 +0000262
Kate Stonee2b21862014-07-22 17:03:38 +0000263 //----------------------------------------------------
264 // Range and state management
265 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000266
267 int
268 GetStartCookie()
Kate Stonee2b21862014-07-22 17:03:38 +0000269 {
Jason Molenda026aa492014-10-15 22:11:15 +0000270 return (int)(m_write_ptr - m_buffer);
Kate Stonee2b21862014-07-22 17:03:38 +0000271 }
Jason Molenda026aa492014-10-15 22:11:15 +0000272
273 BufferRange
274 EndRange(int start_cookie)
Kate Stonee2b21862014-07-22 17:03:38 +0000275 {
Jason Molenda026aa492014-10-15 22:11:15 +0000276 return { start_cookie, (int)(m_write_ptr - (m_buffer + start_cookie)) };
Kate Stonee2b21862014-07-22 17:03:38 +0000277 }
Jason Molenda026aa492014-10-15 22:11:15 +0000278
279 void
280 ReorderRange(BufferRange source_range, int insertion_point_cookie)
Kate Stonee2b21862014-07-22 17:03:38 +0000281 {
282 // Ensure there's room the preserve the source range
Jason Molenda026aa492014-10-15 22:11:15 +0000283 if (m_write_ptr + source_range.length > m_buffer_end)
Kate Stonee2b21862014-07-22 17:03:38 +0000284 {
Jason Molenda026aa492014-10-15 22:11:15 +0000285 GrowBuffer(m_write_ptr + source_range.length - m_buffer_end);
Kate Stonee2b21862014-07-22 17:03:38 +0000286 }
Jason Molenda026aa492014-10-15 22:11:15 +0000287
Kate Stonee2b21862014-07-22 17:03:38 +0000288 // Reorder the content
Jason Molenda026aa492014-10-15 22:11:15 +0000289 memcpy(m_write_ptr, m_buffer + source_range.offset, source_range.length);
290 memmove(m_buffer + insertion_point_cookie + source_range.length,
291 m_buffer + insertion_point_cookie,
Kate Stonee2b21862014-07-22 17:03:38 +0000292 source_range.offset - insertion_point_cookie);
Jason Molenda026aa492014-10-15 22:11:15 +0000293 memcpy(m_buffer + insertion_point_cookie, m_write_ptr, source_range.length);
294
Kate Stonee2b21862014-07-22 17:03:38 +0000295 // Fix up rewritable ranges, covering both substitutions and templates
296 int index = 0;
297 while (true)
298 {
Jason Molenda026aa492014-10-15 22:11:15 +0000299 if (index == m_next_substitute_index)
300 index = m_next_template_arg_index + 1;
301 if (index == m_rewrite_ranges_size)
302 break;
303
Kate Stonee2b21862014-07-22 17:03:38 +0000304 // Affected ranges are either shuffled forward when after the
305 // insertion but before the source, or backward when inside the
306 // source
Jason Molenda026aa492014-10-15 22:11:15 +0000307 int candidate_offset = m_rewrite_ranges[index].offset;
Kate Stonee2b21862014-07-22 17:03:38 +0000308 if (candidate_offset >= insertion_point_cookie)
309 {
310 if (candidate_offset < source_range.offset)
311 {
Jason Molenda026aa492014-10-15 22:11:15 +0000312 m_rewrite_ranges[index].offset += source_range.length;
Kate Stonee2b21862014-07-22 17:03:38 +0000313 }
314 else if (candidate_offset >= source_range.offset)
315 {
Jason Molenda026aa492014-10-15 22:11:15 +0000316 m_rewrite_ranges[index].offset -= (source_range.offset - insertion_point_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +0000317 }
318 }
319 ++index;
320 }
321 }
Jason Molenda026aa492014-10-15 22:11:15 +0000322
323 void
324 EndSubstitution(int start_cookie)
Kate Stonee2b21862014-07-22 17:03:38 +0000325 {
Jason Molenda026aa492014-10-15 22:11:15 +0000326 if (m_next_substitute_index == m_next_template_arg_index)
327 GrowRewriteRanges();
328
329 int index = m_next_substitute_index++;
330 m_rewrite_ranges[index] = EndRange(start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +0000331#ifdef DEBUG_SUBSTITUTIONS
332 printf("Saved substitution # %d = %.*s\n", index,
Jason Molenda026aa492014-10-15 22:11:15 +0000333 m_rewrite_ranges[index].length, m_buffer + start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +0000334#endif
335 }
Jason Molenda026aa492014-10-15 22:11:15 +0000336
337 void
338 EndTemplateArg(int start_cookie)
Kate Stonee2b21862014-07-22 17:03:38 +0000339 {
Jason Molenda026aa492014-10-15 22:11:15 +0000340 if (m_next_substitute_index == m_next_template_arg_index)
341 GrowRewriteRanges();
342
343 int index = m_next_template_arg_index--;
344 m_rewrite_ranges[index] = EndRange(start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +0000345#ifdef DEBUG_TEMPLATE_ARGS
346 printf("Saved template arg # %d = %.*s\n",
Jason Molenda026aa492014-10-15 22:11:15 +0000347 m_rewrite_ranges_size - index - 1,
348 m_rewrite_ranges[index].length, m_buffer + start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +0000349#endif
350 }
Jason Molenda026aa492014-10-15 22:11:15 +0000351
352 void
353 ResetTemplateArgs()
Kate Stonee2b21862014-07-22 17:03:38 +0000354 {
355 //TODO: this works, but is it the right thing to do?
356 // Should we push/pop somehow at the call sites?
Jason Molenda026aa492014-10-15 22:11:15 +0000357 m_next_template_arg_index = m_rewrite_ranges_size - 1;
Kate Stonee2b21862014-07-22 17:03:38 +0000358 }
Jason Molenda026aa492014-10-15 22:11:15 +0000359
Kate Stonee2b21862014-07-22 17:03:38 +0000360 //----------------------------------------------------
361 // Write methods
362 //
363 // Appends content to the existing output buffer
364 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000365
366 void
367 Write(char character)
Kate Stonee2b21862014-07-22 17:03:38 +0000368 {
Jason Molenda026aa492014-10-15 22:11:15 +0000369 if (m_write_ptr == m_buffer_end)
370 GrowBuffer();
371 *m_write_ptr++ = character;
Kate Stonee2b21862014-07-22 17:03:38 +0000372 }
Jason Molenda026aa492014-10-15 22:11:15 +0000373
374 void
375 Write(const char *content)
Kate Stonee2b21862014-07-22 17:03:38 +0000376 {
377 Write(content, strlen(content));
378 }
Jason Molenda026aa492014-10-15 22:11:15 +0000379
380 void
381 Write(const char *content, long content_length)
Kate Stonee2b21862014-07-22 17:03:38 +0000382 {
Jason Molenda026aa492014-10-15 22:11:15 +0000383 char *end_m_write_ptr = m_write_ptr + content_length;
384 if (end_m_write_ptr > m_buffer_end)
Kate Stonee2b21862014-07-22 17:03:38 +0000385 {
Jason Molendaebd01b02015-04-30 23:42:56 +0000386 if (content >= m_buffer && content < m_buffer_end)
387 {
388 long offset = content - m_buffer;
389 GrowBuffer (end_m_write_ptr - m_buffer_end);
390 content = m_buffer + offset;
391 }
392 else
393 {
394 GrowBuffer (end_m_write_ptr - m_buffer_end);
395 }
Jason Molenda026aa492014-10-15 22:11:15 +0000396 end_m_write_ptr = m_write_ptr + content_length;
Kate Stonee2b21862014-07-22 17:03:38 +0000397 }
Jason Molendaebd01b02015-04-30 23:42:56 +0000398 memcpy (m_write_ptr, content, content_length);
Jason Molenda026aa492014-10-15 22:11:15 +0000399 m_write_ptr = end_m_write_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000400 }
Jason Molenda026aa492014-10-15 22:11:15 +0000401#define WRITE(x) Write(x, sizeof (x) - 1)
402
403 void
404 WriteTemplateStart()
Kate Stonee2b21862014-07-22 17:03:38 +0000405 {
406 Write('<');
407 }
Jason Molenda026aa492014-10-15 22:11:15 +0000408
409 void
410 WriteTemplateEnd()
Kate Stonee2b21862014-07-22 17:03:38 +0000411 {
412 // Put a space between terminal > characters when nesting templates
Jason Molenda026aa492014-10-15 22:11:15 +0000413 if (m_write_ptr != m_buffer && *(m_write_ptr - 1) == '>')
414 WRITE(" >");
Kate Stonee2b21862014-07-22 17:03:38 +0000415 else Write('>');
416 }
Jason Molenda026aa492014-10-15 22:11:15 +0000417
418 void
419 WriteCommaSpace()
Kate Stonee2b21862014-07-22 17:03:38 +0000420 {
421 WRITE(", ");
422 }
Jason Molenda026aa492014-10-15 22:11:15 +0000423
424 void
425 WriteNamespaceSeparator()
Kate Stonee2b21862014-07-22 17:03:38 +0000426 {
427 WRITE("::");
428 }
Jason Molenda026aa492014-10-15 22:11:15 +0000429
430 void
431 WriteStdPrefix()
Kate Stonee2b21862014-07-22 17:03:38 +0000432 {
433 WRITE("std::");
434 }
Jason Molenda026aa492014-10-15 22:11:15 +0000435
436 void
437 WriteQualifiers(int qualifiers, bool space_before_reference = true)
Kate Stonee2b21862014-07-22 17:03:38 +0000438 {
Jason Molenda026aa492014-10-15 22:11:15 +0000439 if (qualifiers & QualifierPointer)
440 Write('*');
441 if (qualifiers & QualifierConst)
442 WRITE(" const");
443 if (qualifiers & QualifierVolatile)
444 WRITE(" volatile");
445 if (qualifiers & QualifierRestrict)
446 WRITE(" restrict");
Kate Stonee2b21862014-07-22 17:03:38 +0000447 if (qualifiers & QualifierReference)
448 {
Jason Molenda026aa492014-10-15 22:11:15 +0000449 if (space_before_reference)
450 WRITE(" &");
Kate Stonee2b21862014-07-22 17:03:38 +0000451 else Write('&');
452 }
453 if (qualifiers & QualifierRValueReference)
454 {
Jason Molenda026aa492014-10-15 22:11:15 +0000455 if (space_before_reference)
456 WRITE(" &&");
Kate Stonee2b21862014-07-22 17:03:38 +0000457 else WRITE("&&");
458 }
459 }
Jason Molenda026aa492014-10-15 22:11:15 +0000460
Kate Stonee2b21862014-07-22 17:03:38 +0000461 //----------------------------------------------------
462 // Rewrite methods
463 //
464 // Write another copy of content already present
465 // earlier in the output buffer
466 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000467
468 void
469 RewriteRange(BufferRange range)
Kate Stonee2b21862014-07-22 17:03:38 +0000470 {
Jason Molenda026aa492014-10-15 22:11:15 +0000471 Write(m_buffer + range.offset, range.length);
Kate Stonee2b21862014-07-22 17:03:38 +0000472 }
Jason Molenda026aa492014-10-15 22:11:15 +0000473
474 bool
475 RewriteSubstitution(int index)
Kate Stonee2b21862014-07-22 17:03:38 +0000476 {
Jason Molenda026aa492014-10-15 22:11:15 +0000477 if (index < 0 || index >= m_next_substitute_index)
Kate Stonee2b21862014-07-22 17:03:38 +0000478 {
479#ifdef DEBUG_FAILURES
480 printf("*** Invalid substitution #%d\n", index);
481#endif
482 return false;
483 }
Jason Molenda026aa492014-10-15 22:11:15 +0000484 RewriteRange(m_rewrite_ranges[index]);
Kate Stonee2b21862014-07-22 17:03:38 +0000485 return true;
486 }
Jason Molenda026aa492014-10-15 22:11:15 +0000487
488 bool
489 RewriteTemplateArg(int template_index)
Kate Stonee2b21862014-07-22 17:03:38 +0000490 {
Jason Molenda026aa492014-10-15 22:11:15 +0000491 int index = m_rewrite_ranges_size - 1 - template_index;
492 if (template_index < 0 || index <= m_next_template_arg_index)
Kate Stonee2b21862014-07-22 17:03:38 +0000493 {
494#ifdef DEBUG_FAILURES
495 printf("*** Invalid template arg reference #%d\n", template_index);
496#endif
497 return false;
498 }
Jason Molenda026aa492014-10-15 22:11:15 +0000499 RewriteRange(m_rewrite_ranges[index]);
Kate Stonee2b21862014-07-22 17:03:38 +0000500 return true;
501 }
Jason Molenda026aa492014-10-15 22:11:15 +0000502
Kate Stonee2b21862014-07-22 17:03:38 +0000503 //----------------------------------------------------
504 // TryParse methods
505 //
506 // Provide information with return values instead of
507 // writing to the output buffer
508 //
509 // Values indicating failure guarantee that the pre-
Jason Molenda026aa492014-10-15 22:11:15 +0000510 // call m_read_ptr is unchanged
Kate Stonee2b21862014-07-22 17:03:38 +0000511 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000512
513 int
514 TryParseNumber()
Kate Stonee2b21862014-07-22 17:03:38 +0000515 {
Jason Molenda026aa492014-10-15 22:11:15 +0000516 unsigned char digit = *m_read_ptr - '0';
517 if (digit > 9)
518 return -1;
519
Kate Stonee2b21862014-07-22 17:03:38 +0000520 int count = digit;
521 while (true)
522 {
Jason Molenda026aa492014-10-15 22:11:15 +0000523 digit = *++m_read_ptr - '0';
524 if (digit > 9)
525 break;
526
Kate Stonee2b21862014-07-22 17:03:38 +0000527 count = count * 10 + digit;
528 }
529 return count;
530 }
Jason Molenda026aa492014-10-15 22:11:15 +0000531
532 int
533 TryParseBase36Number()
Kate Stonee2b21862014-07-22 17:03:38 +0000534 {
Jason Molenda026aa492014-10-15 22:11:15 +0000535 char digit = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000536 int count;
Jason Molenda026aa492014-10-15 22:11:15 +0000537 if (digit >= '0' && digit <= '9')
538 count = digit -= '0';
539 else if (digit >= 'A' && digit <= 'Z')
540 count = digit -= ('A' - 10);
Kate Stonee2b21862014-07-22 17:03:38 +0000541 else return -1;
Jason Molenda026aa492014-10-15 22:11:15 +0000542
Kate Stonee2b21862014-07-22 17:03:38 +0000543 while (true)
544 {
Jason Molenda026aa492014-10-15 22:11:15 +0000545 digit = *++m_read_ptr;
546 if (digit >= '0' && digit <= '9')
547 digit -= '0';
548 else if (digit >= 'A' && digit <= 'Z')
549 digit -= ('A' - 10);
Kate Stonee2b21862014-07-22 17:03:38 +0000550 else break;
Jason Molenda026aa492014-10-15 22:11:15 +0000551
Kate Stonee2b21862014-07-22 17:03:38 +0000552 count = count * 36 + digit;
553 }
554 return count;
555 }
Jason Molenda026aa492014-10-15 22:11:15 +0000556
Kate Stonee2b21862014-07-22 17:03:38 +0000557 // <builtin-type> ::= v # void
558 // ::= w # wchar_t
559 // ::= b # bool
560 // ::= c # char
561 // ::= a # signed char
562 // ::= h # unsigned char
563 // ::= s # short
564 // ::= t # unsigned short
565 // ::= i # int
566 // ::= j # unsigned int
567 // ::= l # long
568 // ::= m # unsigned long
569 // ::= x # long long, __int64
570 // ::= y # unsigned long long, __int64
571 // ::= n # __int128
572 // ::= o # unsigned __int128
573 // ::= f # float
574 // ::= d # double
575 // ::= e # long double, __float80
576 // ::= g # __float128
577 // ::= z # ellipsis
578 // ::= Dd # IEEE 754r decimal floating point (64 bits)
579 // ::= De # IEEE 754r decimal floating point (128 bits)
580 // ::= Df # IEEE 754r decimal floating point (32 bits)
581 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
582 // ::= Di # char32_t
583 // ::= Ds # char16_t
584 // ::= Da # auto (in dependent new-expressions)
585 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
586 // ::= u <source-name> # vendor extended type
Jason Molenda026aa492014-10-15 22:11:15 +0000587
588 const char *
589 TryParseBuiltinType()
Kate Stonee2b21862014-07-22 17:03:38 +0000590 {
Jason Molenda026aa492014-10-15 22:11:15 +0000591 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000592 {
593 case 'v': return "void";
594 case 'w': return "wchar_t";
595 case 'b': return "bool";
596 case 'c': return "char";
597 case 'a': return "signed char";
598 case 'h': return "unsigned char";
599 case 's': return "short";
600 case 't': return "unsigned short";
601 case 'i': return "int";
602 case 'j': return "unsigned int";
603 case 'l': return "long";
604 case 'm': return "unsigned long";
605 case 'x': return "long long";
606 case 'y': return "unsigned long long";
607 case 'n': return "__int128";
608 case 'o': return "unsigned __int128";
609 case 'f': return "float";
610 case 'd': return "double";
611 case 'e': return "long double";
612 case 'g': return "__float128";
613 case 'z': return "...";
614 case 'D':
615 {
Jason Molenda026aa492014-10-15 22:11:15 +0000616 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000617 {
618 case 'd': return "decimal64";
619 case 'e': return "decimal128";
620 case 'f': return "decimal32";
621 case 'h': return "decimal16";
622 case 'i': return "char32_t";
623 case 's': return "char16_t";
624 case 'a': return "auto";
625 case 'c': return "decltype(auto)";
626 case 'n': return "std::nullptr_t";
627 default:
Jason Molenda026aa492014-10-15 22:11:15 +0000628 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000629 }
630 }
631 }
Jason Molenda026aa492014-10-15 22:11:15 +0000632 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000633 return nullptr;
634 }
Jason Molenda026aa492014-10-15 22:11:15 +0000635
Kate Stonee2b21862014-07-22 17:03:38 +0000636 // <operator-name>
637 // ::= aa # &&
638 // ::= ad # & (unary)
639 // ::= an # &
640 // ::= aN # &=
641 // ::= aS # =
642 // ::= cl # ()
643 // ::= cm # ,
644 // ::= co # ~
645 // ::= da # delete[]
646 // ::= de # * (unary)
647 // ::= dl # delete
648 // ::= dv # /
649 // ::= dV # /=
650 // ::= eo # ^
651 // ::= eO # ^=
652 // ::= eq # ==
653 // ::= ge # >=
654 // ::= gt # >
655 // ::= ix # []
656 // ::= le # <=
657 // ::= ls # <<
658 // ::= lS # <<=
659 // ::= lt # <
660 // ::= mi # -
661 // ::= mI # -=
662 // ::= ml # *
663 // ::= mL # *=
664 // ::= mm # -- (postfix in <expression> context)
665 // ::= na # new[]
666 // ::= ne # !=
667 // ::= ng # - (unary)
668 // ::= nt # !
669 // ::= nw # new
670 // ::= oo # ||
671 // ::= or # |
672 // ::= oR # |=
673 // ::= pm # ->*
674 // ::= pl # +
675 // ::= pL # +=
676 // ::= pp # ++ (postfix in <expression> context)
677 // ::= ps # + (unary)
678 // ::= pt # ->
679 // ::= qu # ?
680 // ::= rm # %
681 // ::= rM # %=
682 // ::= rs # >>
683 // ::= rS # >>=
684 // ::= cv <type> # (cast)
685 // ::= v <digit> <source-name> # vendor extended operator
Jason Molenda026aa492014-10-15 22:11:15 +0000686
687 Operator
688 TryParseOperator()
Kate Stonee2b21862014-07-22 17:03:38 +0000689 {
Jason Molenda026aa492014-10-15 22:11:15 +0000690 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000691 {
692 case 'a':
Jason Molenda026aa492014-10-15 22:11:15 +0000693 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000694 {
695 case 'a': return { "&&", OperatorKind::Binary };
696 case 'd': return { "&", OperatorKind::Unary };
697 case 'n': return { "&", OperatorKind::Binary };
698 case 'N': return { "&=", OperatorKind::Binary };
699 case 'S': return { "=", OperatorKind::Binary };
700 }
Jason Molenda026aa492014-10-15 22:11:15 +0000701 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000702 break;
703 case 'c':
Jason Molenda026aa492014-10-15 22:11:15 +0000704 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000705 {
706 case 'l': return { "()", OperatorKind::Other };
707 case 'm': return { ",", OperatorKind::Other };
708 case 'o': return { "~", OperatorKind::Unary };
709 case 'v': return { nullptr, OperatorKind::ConversionOperator };
710 }
Jason Molenda026aa492014-10-15 22:11:15 +0000711 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000712 break;
713 case 'd':
Jason Molenda026aa492014-10-15 22:11:15 +0000714 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000715 {
716 case 'a': return { " delete[]", OperatorKind::Other };
717 case 'e': return { "*", OperatorKind::Unary };
718 case 'l': return { " delete", OperatorKind::Other };
719 case 'v': return { "/", OperatorKind::Binary };
720 case 'V': return { "/=", OperatorKind::Binary };
721 }
Jason Molenda026aa492014-10-15 22:11:15 +0000722 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000723 break;
724 case 'e':
Jason Molenda026aa492014-10-15 22:11:15 +0000725 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000726 {
727 case 'o': return { "^", OperatorKind::Binary };
728 case 'O': return { "^=", OperatorKind::Binary };
729 case 'q': return { "==", OperatorKind::Binary };
730 }
Jason Molenda026aa492014-10-15 22:11:15 +0000731 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000732 break;
733 case 'g':
Jason Molenda026aa492014-10-15 22:11:15 +0000734 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000735 {
736 case 'e': return { ">=", OperatorKind::Binary };
737 case 't': return { ">", OperatorKind::Binary };
738 }
Jason Molenda026aa492014-10-15 22:11:15 +0000739 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000740 break;
741 case 'i':
Jason Molenda026aa492014-10-15 22:11:15 +0000742 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000743 {
744 case 'x': return { "[]", OperatorKind::Other };
745 }
Jason Molenda026aa492014-10-15 22:11:15 +0000746 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000747 break;
748 case 'l':
Jason Molenda026aa492014-10-15 22:11:15 +0000749 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000750 {
751 case 'e': return { "<=", OperatorKind::Binary };
752 case 's': return { "<<", OperatorKind::Binary };
753 case 'S': return { "<<=", OperatorKind::Binary };
754 case 't': return { "<", OperatorKind::Binary };
755 // case 'i': return { "?", OperatorKind::Binary };
756 }
Jason Molenda026aa492014-10-15 22:11:15 +0000757 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000758 break;
759 case 'm':
Jason Molenda026aa492014-10-15 22:11:15 +0000760 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000761 {
762 case 'i': return { "-", OperatorKind::Binary };
763 case 'I': return { "-=", OperatorKind::Binary };
764 case 'l': return { "*", OperatorKind::Binary };
765 case 'L': return { "*=", OperatorKind::Binary };
766 case 'm': return { "--", OperatorKind::Postfix };
767 }
Jason Molenda026aa492014-10-15 22:11:15 +0000768 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000769 break;
770 case 'n':
Jason Molenda026aa492014-10-15 22:11:15 +0000771 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000772 {
773 case 'a': return { " new[]", OperatorKind::Other };
774 case 'e': return { "!=", OperatorKind::Binary };
775 case 'g': return { "-", OperatorKind::Unary };
776 case 't': return { "!", OperatorKind::Unary };
777 case 'w': return { " new", OperatorKind::Other };
778 }
Jason Molenda026aa492014-10-15 22:11:15 +0000779 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000780 break;
781 case 'o':
Jason Molenda026aa492014-10-15 22:11:15 +0000782 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000783 {
784 case 'o': return { "||", OperatorKind::Binary };
785 case 'r': return { "|", OperatorKind::Binary };
786 case 'R': return { "|=", OperatorKind::Binary };
787 }
Jason Molenda026aa492014-10-15 22:11:15 +0000788 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000789 break;
790 case 'p':
Jason Molenda026aa492014-10-15 22:11:15 +0000791 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000792 {
793 case 'm': return { "->*", OperatorKind::Binary };
794 case 's': return { "+", OperatorKind::Unary };
795 case 'l': return { "+", OperatorKind::Binary };
796 case 'L': return { "+=", OperatorKind::Binary };
797 case 'p': return { "++", OperatorKind::Postfix };
798 case 't': return { "->", OperatorKind::Binary };
799 }
Jason Molenda026aa492014-10-15 22:11:15 +0000800 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000801 break;
802 case 'q':
Jason Molenda026aa492014-10-15 22:11:15 +0000803 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000804 {
805 case 'u': return { "?", OperatorKind::Ternary };
806 }
Jason Molenda026aa492014-10-15 22:11:15 +0000807 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000808 break;
809 case 'r':
Jason Molenda026aa492014-10-15 22:11:15 +0000810 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000811 {
812 case 'm': return { "%", OperatorKind::Binary };
813 case 'M': return { "%=", OperatorKind::Binary };
814 case 's': return { ">>", OperatorKind::Binary };
815 case 'S': return { ">=", OperatorKind::Binary };
816 }
Jason Molenda026aa492014-10-15 22:11:15 +0000817 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000818 break;
819 case 'v':
Jason Molenda026aa492014-10-15 22:11:15 +0000820 char digit = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000821 if (digit >= '0' && digit <= '9')
822 {
Jason Molenda026aa492014-10-15 22:11:15 +0000823 m_read_ptr++;
Kate Stonee2b21862014-07-22 17:03:38 +0000824 return { nullptr, OperatorKind::Vendor };
825 }
Jason Molenda026aa492014-10-15 22:11:15 +0000826 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000827 break;
828 }
Jason Molenda026aa492014-10-15 22:11:15 +0000829 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000830 return { nullptr, OperatorKind::NoMatch };
831 }
Jason Molenda026aa492014-10-15 22:11:15 +0000832
Kate Stonee2b21862014-07-22 17:03:38 +0000833 // <CV-qualifiers> ::= [r] [V] [K]
834 // <ref-qualifier> ::= R # & ref-qualifier
835 // <ref-qualifier> ::= O # && ref-qualifier
Jason Molenda026aa492014-10-15 22:11:15 +0000836
837 int
838 TryParseQualifiers(bool allow_cv, bool allow_ro)
Kate Stonee2b21862014-07-22 17:03:38 +0000839 {
840 int qualifiers = QualifierNone;
Jason Molenda026aa492014-10-15 22:11:15 +0000841 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000842 if (allow_cv)
843 {
844 if (next == 'r') // restrict
845 {
846 qualifiers |= QualifierRestrict;
Jason Molenda026aa492014-10-15 22:11:15 +0000847 next = *++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000848 }
849 if (next == 'V') // volatile
850 {
851 qualifiers |= QualifierVolatile;
Jason Molenda026aa492014-10-15 22:11:15 +0000852 next = *++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000853 }
854 if (next == 'K') // const
855 {
856 qualifiers |= QualifierConst;
Jason Molenda026aa492014-10-15 22:11:15 +0000857 next = *++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000858 }
859 }
860 if (allow_ro)
861 {
862 if (next == 'R')
863 {
Jason Molenda026aa492014-10-15 22:11:15 +0000864 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000865 qualifiers |= QualifierReference;
866 }
867 else if (next =='O')
868 {
Jason Molenda026aa492014-10-15 22:11:15 +0000869 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000870 qualifiers |= QualifierRValueReference;
871 }
872 }
873 return qualifiers;
874 }
Jason Molenda026aa492014-10-15 22:11:15 +0000875
Kate Stonee2b21862014-07-22 17:03:38 +0000876 // <discriminator> := _ <non-negative number> # when number < 10
877 // := __ <non-negative number> _ # when number >= 10
878 // extension := decimal-digit+
Jason Molenda026aa492014-10-15 22:11:15 +0000879
880 int
881 TryParseDiscriminator()
Kate Stonee2b21862014-07-22 17:03:38 +0000882 {
Jason Molenda026aa492014-10-15 22:11:15 +0000883 const char *discriminator_start = m_read_ptr;
884
Kate Stonee2b21862014-07-22 17:03:38 +0000885 // Test the extension first, since it's what Clang uses
886 int discriminator_value = TryParseNumber();
Jason Molenda026aa492014-10-15 22:11:15 +0000887 if (discriminator_value != -1)
888 return discriminator_value;
889
890 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000891 if (next == '_')
892 {
Jason Molenda026aa492014-10-15 22:11:15 +0000893 next = *++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000894 if (next == '_')
895 {
Jason Molenda026aa492014-10-15 22:11:15 +0000896 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000897 discriminator_value = TryParseNumber();
Jason Molenda026aa492014-10-15 22:11:15 +0000898 if (discriminator_value != -1 && *m_read_ptr++ != '_')
Kate Stonee2b21862014-07-22 17:03:38 +0000899 {
900 return discriminator_value;
901 }
902 }
903 else if (next >= '0' && next <= '9')
904 {
Jason Molenda026aa492014-10-15 22:11:15 +0000905 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000906 return next - '0';
907 }
908 }
Jason Molenda026aa492014-10-15 22:11:15 +0000909
Kate Stonee2b21862014-07-22 17:03:38 +0000910 // Not a valid discriminator
Jason Molenda026aa492014-10-15 22:11:15 +0000911 m_read_ptr = discriminator_start;
Kate Stonee2b21862014-07-22 17:03:38 +0000912 return -1;
913 }
Jason Molenda026aa492014-10-15 22:11:15 +0000914
Kate Stonee2b21862014-07-22 17:03:38 +0000915 //----------------------------------------------------
916 // Parse methods
917 //
Jason Molenda026aa492014-10-15 22:11:15 +0000918 // Consume input starting from m_read_ptr and produce
919 // buffered output at m_write_ptr
Kate Stonee2b21862014-07-22 17:03:38 +0000920 //
Jason Molenda026aa492014-10-15 22:11:15 +0000921 // Failures return false and may leave m_read_ptr in an
Kate Stonee2b21862014-07-22 17:03:38 +0000922 // indeterminate state
923 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000924
925 bool
926 Parse(char character)
Kate Stonee2b21862014-07-22 17:03:38 +0000927 {
Jason Molenda026aa492014-10-15 22:11:15 +0000928 if (*m_read_ptr++ == character)
929 return true;
Kate Stonee2b21862014-07-22 17:03:38 +0000930#ifdef DEBUG_FAILURES
931 printf("*** Expected '%c'\n", character);
932#endif
933 return false;
934 }
Jason Molenda026aa492014-10-15 22:11:15 +0000935
Kate Stonee2b21862014-07-22 17:03:38 +0000936 // <number> ::= [n] <non-negative decimal integer>
Jason Molenda026aa492014-10-15 22:11:15 +0000937
938 bool
939 ParseNumber(bool allow_negative = false)
Kate Stonee2b21862014-07-22 17:03:38 +0000940 {
Jason Molenda026aa492014-10-15 22:11:15 +0000941 if (allow_negative && *m_read_ptr == 'n')
Kate Stonee2b21862014-07-22 17:03:38 +0000942 {
943 Write('-');
Jason Molenda026aa492014-10-15 22:11:15 +0000944 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000945 }
Jason Molenda026aa492014-10-15 22:11:15 +0000946 const char *before_digits = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000947 while (true)
948 {
Jason Molenda026aa492014-10-15 22:11:15 +0000949 unsigned char digit = *m_read_ptr - '0';
950 if (digit > 9)
951 break;
952 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000953 }
Jason Molenda026aa492014-10-15 22:11:15 +0000954 if (int digit_count = (int)(m_read_ptr - before_digits))
Kate Stonee2b21862014-07-22 17:03:38 +0000955 {
956 Write(before_digits, digit_count);
957 return true;
958 }
959#ifdef DEBUG_FAILURES
960 printf("*** Expected number\n");
961#endif
962 return false;
963 }
Jason Molenda026aa492014-10-15 22:11:15 +0000964
Kate Stonee2b21862014-07-22 17:03:38 +0000965 // <substitution> ::= S <seq-id> _
966 // ::= S_
967 // <substitution> ::= Sa # ::std::allocator
968 // <substitution> ::= Sb # ::std::basic_string
969 // <substitution> ::= Ss # ::std::basic_string < char,
970 // ::std::char_traits<char>,
971 // ::std::allocator<char> >
972 // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
973 // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
974 // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Jason Molenda026aa492014-10-15 22:11:15 +0000975
976 bool
977 ParseSubstitution()
Kate Stonee2b21862014-07-22 17:03:38 +0000978 {
Jason Molenda026aa492014-10-15 22:11:15 +0000979 const char *substitution;
980 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +0000981 {
982 case 'a': substitution = "std::allocator"; break;
983 case 'b': substitution = "std::basic_string"; break;
984 case 's': substitution = "std::string"; break;
985 case 'i': substitution = "std::istream"; break;
986 case 'o': substitution = "std::ostream"; break;
987 case 'd': substitution = "std::iostream"; break;
988 default:
989 // A failed attempt to parse a number will return -1 which turns out to be
990 // perfect here as S_ is the first substitution, S0_ the next and so forth
991 int substitution_index = TryParseBase36Number();
Jason Molenda026aa492014-10-15 22:11:15 +0000992 if (*m_read_ptr++ != '_')
Kate Stonee2b21862014-07-22 17:03:38 +0000993 {
994#ifdef DEBUG_FAILURES
995 printf("*** Expected terminal _ in substitution\n");
996#endif
997 return false;
998 }
Jason Molenda026aa492014-10-15 22:11:15 +0000999 return RewriteSubstitution (substitution_index + 1);
Kate Stonee2b21862014-07-22 17:03:38 +00001000 }
1001 Write(substitution);
Jason Molenda026aa492014-10-15 22:11:15 +00001002 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001003 return true;
1004 }
Jason Molenda026aa492014-10-15 22:11:15 +00001005
Kate Stonee2b21862014-07-22 17:03:38 +00001006 // <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
1007 //
1008 // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types
Jason Molenda026aa492014-10-15 22:11:15 +00001009
1010 bool
1011 ParseFunctionType (int inner_qualifiers = QualifierNone)
Kate Stonee2b21862014-07-22 17:03:38 +00001012 {
1013#ifdef DEBUG_FAILURES
1014 printf("*** Function types not supported\n");
1015#endif
1016 //TODO: first steps toward an implementation follow, but they're far
1017 // from complete. Function types tend to bracket other types eg:
1018 // int (*)() when used as the type for "name" becomes int (*name)().
1019 // This makes substitution et al ... interesting.
1020 return false;
Jason Molenda026aa492014-10-15 22:11:15 +00001021
Jason Molenda61e0a3e2014-10-17 01:36:20 +00001022#if 0 // TODO
Jason Molenda026aa492014-10-15 22:11:15 +00001023 if (*m_read_ptr == 'Y')
1024 ++m_read_ptr;
1025
Kate Stonee2b21862014-07-22 17:03:38 +00001026 int return_type_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001027 if (!ParseType())
1028 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001029 Write(' ');
Jason Molenda026aa492014-10-15 22:11:15 +00001030
Kate Stonee2b21862014-07-22 17:03:38 +00001031 int insert_cookie = GetStartCookie();
1032 Write('(');
1033 bool first_param = true;
1034 int qualifiers = QualifierNone;
1035 while (true)
1036 {
Jason Molenda026aa492014-10-15 22:11:15 +00001037 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00001038 {
1039 case 'E':
Jason Molenda026aa492014-10-15 22:11:15 +00001040 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001041 Write(')');
1042 break;
1043 case 'v':
Jason Molenda026aa492014-10-15 22:11:15 +00001044 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001045 continue;
1046 case 'R':
1047 case 'O':
Jason Molenda026aa492014-10-15 22:11:15 +00001048 if (*(m_read_ptr + 1) == 'E')
Kate Stonee2b21862014-07-22 17:03:38 +00001049 {
Jason Molenda026aa492014-10-15 22:11:15 +00001050 qualifiers = TryParseQualifiers (false, true);
Kate Stonee2b21862014-07-22 17:03:38 +00001051 Parse('E');
1052 break;
1053 }
1054 // fallthrough
1055 default:
1056 {
Jason Molenda026aa492014-10-15 22:11:15 +00001057 if (first_param)
1058 first_param = false;
Kate Stonee2b21862014-07-22 17:03:38 +00001059 else WriteCommaSpace();
Jason Molenda026aa492014-10-15 22:11:15 +00001060
1061 if (!ParseType())
1062 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001063 continue;
1064 }
1065 }
1066 break;
1067 }
Jason Molenda026aa492014-10-15 22:11:15 +00001068
Kate Stonee2b21862014-07-22 17:03:38 +00001069 if (qualifiers)
1070 {
Jason Molenda026aa492014-10-15 22:11:15 +00001071 WriteQualifiers (qualifiers);
1072 EndSubstitution (return_type_start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001073 }
Jason Molenda026aa492014-10-15 22:11:15 +00001074
Kate Stonee2b21862014-07-22 17:03:38 +00001075 if (inner_qualifiers)
1076 {
1077 int qualifier_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001078 Write ('(');
1079 WriteQualifiers (inner_qualifiers);
1080 Write (')');
1081 ReorderRange (EndRange (qualifier_start_cookie), insert_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001082 }
1083 return true;
Jason Molenda61e0a3e2014-10-17 01:36:20 +00001084#endif // TODO
Kate Stonee2b21862014-07-22 17:03:38 +00001085 }
Jason Molenda026aa492014-10-15 22:11:15 +00001086
Kate Stonee2b21862014-07-22 17:03:38 +00001087 // <array-type> ::= A <positive dimension number> _ <element type>
1088 // ::= A [<dimension expression>] _ <element type>
Jason Molenda026aa492014-10-15 22:11:15 +00001089
1090 bool
1091 ParseArrayType(int qualifiers = QualifierNone)
Kate Stonee2b21862014-07-22 17:03:38 +00001092 {
1093#ifdef DEBUG_FAILURES
1094 printf("*** Array type unsupported\n");
1095#endif
1096 //TODO: We fail horribly when recalling these as substitutions or
1097 // templates and trying to constify them eg:
1098 // _ZN4llvm2cl5applyIA28_cNS0_3optIbLb0ENS0_6parserIbEEEEEEvRKT_PT0_
1099 //
1100 //TODO: Chances are we don't do any better with references and pointers
1101 // that should be type (&) [] instead of type & []
Jason Molenda026aa492014-10-15 22:11:15 +00001102
Kate Stonee2b21862014-07-22 17:03:38 +00001103 return false;
Jason Molenda026aa492014-10-15 22:11:15 +00001104
Jason Molenda61e0a3e2014-10-17 01:36:20 +00001105#if 0 // TODO
Jason Molenda026aa492014-10-15 22:11:15 +00001106 if (*m_read_ptr == '_')
Kate Stonee2b21862014-07-22 17:03:38 +00001107 {
Jason Molenda026aa492014-10-15 22:11:15 +00001108 ++m_read_ptr;
1109 if (!ParseType())
1110 return false;
1111 if (qualifiers)
1112 WriteQualifiers(qualifiers);
Kate Stonee2b21862014-07-22 17:03:38 +00001113 WRITE(" []");
1114 return true;
1115 }
1116 else
1117 {
Jason Molenda026aa492014-10-15 22:11:15 +00001118 const char *before_digits = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001119 if (TryParseNumber() != -1)
1120 {
Jason Molenda026aa492014-10-15 22:11:15 +00001121 const char *after_digits = m_read_ptr;
1122 if (!Parse('_'))
1123 return false;
1124 if (!ParseType())
1125 return false;
1126 if (qualifiers)
1127 WriteQualifiers(qualifiers);
Kate Stonee2b21862014-07-22 17:03:38 +00001128 Write(' ');
1129 Write('[');
1130 Write(before_digits, after_digits - before_digits);
1131 }
1132 else
1133 {
1134 int type_insertion_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001135 if (!ParseExpression())
1136 return false;
1137 if (!Parse('_'))
1138 return false;
1139
Kate Stonee2b21862014-07-22 17:03:38 +00001140 int type_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001141 if (!ParseType())
1142 return false;
1143 if (qualifiers)
1144 WriteQualifiers(qualifiers);
Kate Stonee2b21862014-07-22 17:03:38 +00001145 Write(' ');
1146 Write('[');
Jason Molenda026aa492014-10-15 22:11:15 +00001147 ReorderRange (EndRange (type_start_cookie), type_insertion_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001148 }
1149 Write(']');
1150 return true;
1151 }
Jason Molenda61e0a3e2014-10-17 01:36:20 +00001152#endif // TODO
Kate Stonee2b21862014-07-22 17:03:38 +00001153 }
Jason Molenda026aa492014-10-15 22:11:15 +00001154
Kate Stonee2b21862014-07-22 17:03:38 +00001155 // <pointer-to-member-type> ::= M <class type> <member type>
Jason Molenda026aa492014-10-15 22:11:15 +00001156
Kate Stonee2b21862014-07-22 17:03:38 +00001157 //TODO: Determine how to handle pointers to function members correctly,
1158 // currently not an issue because we don't have function types at all...
Jason Molenda026aa492014-10-15 22:11:15 +00001159 bool
1160 ParsePointerToMemberType()
Kate Stonee2b21862014-07-22 17:03:38 +00001161 {
1162 int insertion_cookie = GetStartCookie();
1163 Write(' ');
Jason Molenda026aa492014-10-15 22:11:15 +00001164 if (!ParseType())
1165 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001166 WRITE("::*");
Jason Molenda026aa492014-10-15 22:11:15 +00001167
Kate Stonee2b21862014-07-22 17:03:38 +00001168 int type_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001169 if (!ParseType())
1170 return false;
1171 ReorderRange (EndRange (type_cookie), insertion_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001172 return true;
1173 }
Jason Molenda026aa492014-10-15 22:11:15 +00001174
Kate Stonee2b21862014-07-22 17:03:38 +00001175 // <template-param> ::= T_ # first template parameter
1176 // ::= T <parameter-2 non-negative number> _
Jason Molenda026aa492014-10-15 22:11:15 +00001177
1178 bool
1179 ParseTemplateParam()
Kate Stonee2b21862014-07-22 17:03:38 +00001180 {
1181 int count = TryParseNumber();
Jason Molenda026aa492014-10-15 22:11:15 +00001182 if (!Parse('_'))
1183 return false;
1184
Kate Stonee2b21862014-07-22 17:03:38 +00001185 // When no number is present we get -1, which is convenient since
1186 // T_ is the zeroth element T0_ is element 1, and so on
Jason Molenda026aa492014-10-15 22:11:15 +00001187 return RewriteTemplateArg (count + 1);
Kate Stonee2b21862014-07-22 17:03:38 +00001188 }
Jason Molenda026aa492014-10-15 22:11:15 +00001189
Kate Stonee2b21862014-07-22 17:03:38 +00001190 // <type> ::= <builtin-type>
1191 // ::= <function-type>
1192 // ::= <class-enum-type>
1193 // ::= <array-type>
1194 // ::= <pointer-to-member-type>
1195 // ::= <template-param>
1196 // ::= <template-template-param> <template-args>
1197 // ::= <decltype>
1198 // ::= <substitution>
1199 // ::= <CV-qualifiers> <type>
1200 // ::= P <type> # pointer-to
1201 // ::= R <type> # reference-to
1202 // ::= O <type> # rvalue reference-to (C++0x)
1203 // ::= C <type> # complex pair (C 2000)
1204 // ::= G <type> # imaginary (C 2000)
1205 // ::= Dp <type> # pack expansion (C++0x)
1206 // ::= U <source-name> <type> # vendor extended type qualifier
1207 // extension := U <objc-name> <objc-type> # objc-type<identifier>
1208 // extension := <vector-type> # <vector-type> starts with Dv
Jason Molenda026aa492014-10-15 22:11:15 +00001209
Kate Stonee2b21862014-07-22 17:03:38 +00001210 // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
1211 // <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001212
1213 bool
1214 ParseType()
Kate Stonee2b21862014-07-22 17:03:38 +00001215 {
1216#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001217 const char *failed_type = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001218#endif
1219 int type_start_cookie = GetStartCookie();
1220 bool suppress_substitution = false;
Jason Molenda026aa492014-10-15 22:11:15 +00001221
1222 int qualifiers = TryParseQualifiers (true, false);
1223 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00001224 {
1225 case 'D':
Jason Molenda026aa492014-10-15 22:11:15 +00001226 ++m_read_ptr;
1227 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001228 {
1229 case 'p':
Jason Molenda026aa492014-10-15 22:11:15 +00001230 if (!ParseType())
1231 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001232 break;
1233 case 'T':
1234 case 't':
1235 case 'v':
1236 default:
1237#ifdef DEBUG_FAILURES
1238 printf("*** Unsupported type: %.3s\n", failed_type);
1239#endif
1240 return false;
1241 }
1242 break;
1243 case 'T':
Jason Molenda026aa492014-10-15 22:11:15 +00001244 ++m_read_ptr;
1245 if (!ParseTemplateParam())
1246 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001247 break;
1248 case 'M':
Jason Molenda026aa492014-10-15 22:11:15 +00001249 ++m_read_ptr;
1250 if (!ParsePointerToMemberType())
1251 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001252 break;
1253 case 'A':
Jason Molenda026aa492014-10-15 22:11:15 +00001254 ++m_read_ptr;
1255 if (!ParseArrayType())
1256 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001257 break;
1258 case 'F':
Jason Molenda026aa492014-10-15 22:11:15 +00001259 ++m_read_ptr;
1260 if (!ParseFunctionType())
1261 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001262 break;
1263 case 'S':
Jason Molenda026aa492014-10-15 22:11:15 +00001264 if (*++m_read_ptr == 't')
Kate Stonee2b21862014-07-22 17:03:38 +00001265 {
Jason Molenda026aa492014-10-15 22:11:15 +00001266 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001267 WriteStdPrefix();
Jason Molenda026aa492014-10-15 22:11:15 +00001268 if (!ParseName())
1269 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001270 }
1271 else
1272 {
1273 suppress_substitution = true;
Jason Molenda026aa492014-10-15 22:11:15 +00001274 if (!ParseSubstitution())
1275 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001276 }
1277 break;
1278 case 'P':
1279 {
Jason Molenda026aa492014-10-15 22:11:15 +00001280 switch (*++m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00001281 {
1282 case 'F':
Jason Molenda026aa492014-10-15 22:11:15 +00001283 ++m_read_ptr;
1284 if (!ParseFunctionType(QualifierPointer))
1285 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001286 break;
1287 default:
Jason Molenda026aa492014-10-15 22:11:15 +00001288 if (!ParseType())
1289 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001290 Write('*');
1291 break;
1292 }
1293 break;
1294 }
1295 case 'R':
1296 {
Jason Molenda026aa492014-10-15 22:11:15 +00001297 ++m_read_ptr;
1298 if (!ParseType())
1299 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001300 Write('&');
1301 break;
1302 }
1303 case 'O':
1304 {
Jason Molenda026aa492014-10-15 22:11:15 +00001305 ++m_read_ptr;
1306 if (!ParseType())
1307 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001308 Write('&');
1309 Write('&');
1310 break;
1311 }
1312 case 'C':
1313 case 'G':
1314 case 'U':
1315#ifdef DEBUG_FAILURES
1316 printf("*** Unsupported type: %.3s\n", failed_type);
1317#endif
1318 return false;
1319 // Test for common cases to avoid TryParseBuiltinType() overhead
1320 case 'N':
1321 case 'Z':
1322 case 'L':
Jason Molenda026aa492014-10-15 22:11:15 +00001323 if (!ParseName())
1324 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001325 break;
1326 default:
Jason Molenda026aa492014-10-15 22:11:15 +00001327 if (const char *builtin = TryParseBuiltinType())
Kate Stonee2b21862014-07-22 17:03:38 +00001328 {
1329 Write(builtin);
1330 suppress_substitution = true;
1331 }
1332 else
1333 {
Jason Molenda026aa492014-10-15 22:11:15 +00001334 if (!ParseName())
1335 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001336 }
1337 break;
1338 }
Jason Molenda026aa492014-10-15 22:11:15 +00001339
Kate Stonee2b21862014-07-22 17:03:38 +00001340 // Allow base substitutions to be suppressed, but always record
1341 // substitutions for the qualified variant
Jason Molenda026aa492014-10-15 22:11:15 +00001342 if (!suppress_substitution)
1343 EndSubstitution(type_start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001344 if (qualifiers)
1345 {
1346 WriteQualifiers(qualifiers, false);
1347 EndSubstitution(type_start_cookie);
1348 }
1349 return true;
1350 }
Jason Molenda026aa492014-10-15 22:11:15 +00001351
Kate Stonee2b21862014-07-22 17:03:38 +00001352 // <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
1353 // ::= <closure-type-name>
1354 //
1355 // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
1356 //
1357 // <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Jason Molenda026aa492014-10-15 22:11:15 +00001358
1359 bool
1360 ParseUnnamedTypeName(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001361 {
Jason Molenda026aa492014-10-15 22:11:15 +00001362 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001363 {
1364 case 't':
1365 {
1366 int cookie = GetStartCookie();
1367 WRITE("'unnamed");
Jason Molenda026aa492014-10-15 22:11:15 +00001368 const char *before_digits = m_read_ptr;
1369 if (TryParseNumber() != -1) Write (before_digits,
1370 m_read_ptr - before_digits);
1371 if (!Parse('_'))
1372 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001373 Write('\'');
Jason Molenda026aa492014-10-15 22:11:15 +00001374 name_state.last_name_range = EndRange (cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001375 return true;
1376 }
1377 case 'b':
1378 {
1379 int cookie = GetStartCookie();
1380 WRITE("'block");
Jason Molenda026aa492014-10-15 22:11:15 +00001381 const char *before_digits = m_read_ptr;
1382 if (TryParseNumber() != -1) Write (before_digits,
1383 m_read_ptr - before_digits);
1384 if (!Parse('_'))
1385 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001386 Write('\'');
Jason Molenda026aa492014-10-15 22:11:15 +00001387 name_state.last_name_range = EndRange (cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001388 return true;
1389 }
1390 case 'l':
1391#ifdef DEBUG_FAILURES
1392 printf("*** Lambda type names unsupported\n");
1393#endif
1394 return false;
1395 }
1396#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001397 printf("*** Unknown unnamed type %.3s\n", m_read_ptr - 2);
Kate Stonee2b21862014-07-22 17:03:38 +00001398#endif
1399 return false;
1400 }
Jason Molenda026aa492014-10-15 22:11:15 +00001401
Kate Stonee2b21862014-07-22 17:03:38 +00001402 // <ctor-dtor-name> ::= C1 # complete object constructor
1403 // ::= C2 # base object constructor
1404 // ::= C3 # complete object allocating constructor
Jason Molenda026aa492014-10-15 22:11:15 +00001405
1406 bool
1407 ParseCtor(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001408 {
Jason Molenda026aa492014-10-15 22:11:15 +00001409 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001410 if (next == '1' || next == '2' || next == '3' || next == '5')
1411 {
Jason Molenda026aa492014-10-15 22:11:15 +00001412 RewriteRange (name_state.last_name_range);
Kate Stonee2b21862014-07-22 17:03:38 +00001413 name_state.has_no_return_type = true;
Jason Molenda026aa492014-10-15 22:11:15 +00001414 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001415 return true;
1416 }
1417#ifdef DEBUG_FAILURES
1418 printf("*** Broken constructor\n");
1419#endif
1420 return false;
1421 }
Jason Molenda026aa492014-10-15 22:11:15 +00001422
Kate Stonee2b21862014-07-22 17:03:38 +00001423 // <ctor-dtor-name> ::= D0 # deleting destructor
1424 // ::= D1 # complete object destructor
1425 // ::= D2 # base object destructor
Jason Molenda026aa492014-10-15 22:11:15 +00001426
1427 bool
1428 ParseDtor(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001429 {
Jason Molenda026aa492014-10-15 22:11:15 +00001430 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001431 if (next == '0' || next == '1' || next == '2' || next == '5')
1432 {
1433 Write('~');
1434 RewriteRange(name_state.last_name_range);
1435 name_state.has_no_return_type = true;
Jason Molenda026aa492014-10-15 22:11:15 +00001436 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001437 return true;
1438 }
1439#ifdef DEBUG_FAILURES
1440 printf("*** Broken destructor\n");
1441#endif
1442 return false;
1443 }
Jason Molenda026aa492014-10-15 22:11:15 +00001444
Kate Stonee2b21862014-07-22 17:03:38 +00001445 // See TryParseOperator()
Jason Molenda026aa492014-10-15 22:11:15 +00001446
1447 bool
1448 ParseOperatorName(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001449 {
1450#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001451 const char *operator_ptr = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001452#endif
1453 Operator parsed_operator = TryParseOperator();
1454 if (parsed_operator.name)
1455 {
1456 WRITE("operator");
1457 Write(parsed_operator.name);
1458 return true;
1459 }
Jason Molenda026aa492014-10-15 22:11:15 +00001460
Kate Stonee2b21862014-07-22 17:03:38 +00001461 // Handle special operators
1462 switch (parsed_operator.kind)
1463 {
1464 case OperatorKind::Vendor:
1465 WRITE("operator ");
1466 return ParseSourceName();
1467 case OperatorKind::ConversionOperator:
1468 ResetTemplateArgs();
1469 name_state.has_no_return_type = true;
1470 WRITE("operator ");
1471 return ParseType();
1472 default:
1473#ifdef DEBUG_FAILURES
1474 printf("*** Unknown operator: %.2s\n", operator_ptr);
1475#endif
1476 return false;
1477 }
1478 }
Jason Molenda026aa492014-10-15 22:11:15 +00001479
Kate Stonee2b21862014-07-22 17:03:38 +00001480 // <source-name> ::= <positive length number> <identifier>
Jason Molenda026aa492014-10-15 22:11:15 +00001481
1482 bool
1483 ParseSourceName()
Kate Stonee2b21862014-07-22 17:03:38 +00001484 {
1485 int count = TryParseNumber();
1486 if (count == -1)
1487 {
1488#ifdef DEBUG_FAILURES
1489 printf("*** Malformed source name, missing length count\n");
1490#endif
1491 return false;
1492 }
Jason Molenda026aa492014-10-15 22:11:15 +00001493
1494 const char *next_m_read_ptr = m_read_ptr + count;
1495 if (next_m_read_ptr > m_read_end)
Kate Stonee2b21862014-07-22 17:03:38 +00001496 {
1497#ifdef DEBUG_FAILURES
1498 printf("*** Malformed source name, premature termination\n");
1499#endif
1500 return false;
1501 }
Jason Molenda026aa492014-10-15 22:11:15 +00001502
1503 if (count >= 10 && strncmp(m_read_ptr, "_GLOBAL__N", 10) == 0)
1504 WRITE("(anonymous namespace)");
1505 else Write(m_read_ptr, count);
1506
1507 m_read_ptr = next_m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001508 return true;
1509 }
Jason Molenda026aa492014-10-15 22:11:15 +00001510
Kate Stonee2b21862014-07-22 17:03:38 +00001511 // <unqualified-name> ::= <operator-name>
1512 // ::= <ctor-dtor-name>
1513 // ::= <source-name>
1514 // ::= <unnamed-type-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001515
1516 bool
1517 ParseUnqualifiedName(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001518 {
1519 // Note that these are detected directly in ParseNestedName for
1520 // performance rather than switching on the same options twice
Jason Molenda026aa492014-10-15 22:11:15 +00001521 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001522 switch (next)
1523 {
1524 case 'C':
Jason Molenda026aa492014-10-15 22:11:15 +00001525 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001526 return ParseCtor(name_state);
1527 case 'D':
Jason Molenda026aa492014-10-15 22:11:15 +00001528 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001529 return ParseDtor(name_state);
1530 case 'U':
Jason Molenda026aa492014-10-15 22:11:15 +00001531 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001532 return ParseUnnamedTypeName(name_state);
1533 case '0':
1534 case '1':
1535 case '2':
1536 case '3':
1537 case '4':
1538 case '5':
1539 case '6':
1540 case '7':
1541 case '8':
1542 case '9':
1543 {
1544 int name_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001545 if (!ParseSourceName())
1546 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001547 name_state.last_name_range = EndRange(name_start_cookie);
1548 return true;
1549 }
1550 default:
1551 return ParseOperatorName(name_state);
1552 };
1553 }
Jason Molenda026aa492014-10-15 22:11:15 +00001554
Kate Stonee2b21862014-07-22 17:03:38 +00001555 // <unscoped-name> ::= <unqualified-name>
1556 // ::= St <unqualified-name> # ::std::
1557 // extension ::= StL<unqualified-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001558
1559 bool
1560 ParseUnscopedName(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001561 {
Jason Molenda026aa492014-10-15 22:11:15 +00001562 if (*m_read_ptr == 'S' && *(m_read_ptr + 1) == 't')
Kate Stonee2b21862014-07-22 17:03:38 +00001563 {
1564 WriteStdPrefix();
Jason Molenda026aa492014-10-15 22:11:15 +00001565 if (*(m_read_ptr += 2) == 'L')
1566 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001567 }
1568 return ParseUnqualifiedName(name_state);
1569 }
Jason Molenda026aa492014-10-15 22:11:15 +00001570
1571 bool
1572 ParseIntegerLiteral(const char *prefix, const char *suffix,
Kate Stonee2b21862014-07-22 17:03:38 +00001573 bool allow_negative)
1574 {
Jason Molenda026aa492014-10-15 22:11:15 +00001575 if (prefix)
1576 Write(prefix);
1577 if (!ParseNumber(allow_negative))
1578 return false;
1579 if (suffix)
1580 Write(suffix);
Kate Stonee2b21862014-07-22 17:03:38 +00001581 return Parse('E');
1582 }
Jason Molenda026aa492014-10-15 22:11:15 +00001583
1584 bool
1585 ParseBooleanLiteral()
Kate Stonee2b21862014-07-22 17:03:38 +00001586 {
Jason Molenda026aa492014-10-15 22:11:15 +00001587 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001588 {
1589 case '0': WRITE("false"); break;
1590 case '1': WRITE("true"); break;
1591 default:
1592#ifdef DEBUG_FAILURES
1593 printf("*** Boolean literal not 0 or 1\n");
1594#endif
1595 return false;
1596 }
1597 return Parse('E');
1598 }
Jason Molenda026aa492014-10-15 22:11:15 +00001599
Kate Stonee2b21862014-07-22 17:03:38 +00001600 // <expr-primary> ::= L <type> <value number> E # integer literal
1601 // ::= L <type> <value float> E # floating literal
1602 // ::= L <string type> E # string literal
1603 // ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
1604 // ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
1605 // ::= L <mangled-name> E # external name
Jason Molenda026aa492014-10-15 22:11:15 +00001606
1607 bool
1608 ParseExpressionPrimary()
Kate Stonee2b21862014-07-22 17:03:38 +00001609 {
Jason Molenda026aa492014-10-15 22:11:15 +00001610 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001611 {
1612 case 'b': return ParseBooleanLiteral();
1613 case 'x': return ParseIntegerLiteral(nullptr, "ll", true);
1614 case 'l': return ParseIntegerLiteral(nullptr, "l", true);
1615 case 'i': return ParseIntegerLiteral(nullptr, nullptr, true);
1616 case 'n': return ParseIntegerLiteral("(__int128)", nullptr, true);
1617 case 'j': return ParseIntegerLiteral(nullptr, "u", false);
1618 case 'm': return ParseIntegerLiteral(nullptr, "ul", false);
1619 case 'y': return ParseIntegerLiteral(nullptr, "ull", false);
1620 case 'o': return ParseIntegerLiteral("(unsigned __int128)",
1621 nullptr, false);
1622 case '_':
Jason Molenda026aa492014-10-15 22:11:15 +00001623 if (*m_read_ptr++ == 'Z')
Kate Stonee2b21862014-07-22 17:03:38 +00001624 {
Jason Molenda026aa492014-10-15 22:11:15 +00001625 if (!ParseEncoding())
1626 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001627 return Parse('E');
1628 }
Jason Molenda026aa492014-10-15 22:11:15 +00001629 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001630 // fallthrough
1631 case 'w':
1632 case 'c':
1633 case 'a':
1634 case 'h':
1635 case 's':
1636 case 't':
1637 case 'f':
1638 case 'd':
1639 case 'e':
1640#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001641 printf("*** Unsupported primary expression %.5s\n", m_read_ptr - 1);
Kate Stonee2b21862014-07-22 17:03:38 +00001642#endif
1643 return false;
1644 case 'T':
1645 // Invalid mangled name per
1646 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
1647#ifdef DEBUG_FAILURES
1648 printf("*** Invalid primary expr encoding\n");
1649#endif
1650 return false;
1651 default:
Jason Molenda026aa492014-10-15 22:11:15 +00001652 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001653 Write('(');
Jason Molenda026aa492014-10-15 22:11:15 +00001654 if (!ParseType())
1655 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001656 Write(')');
Jason Molenda026aa492014-10-15 22:11:15 +00001657 if (!ParseNumber())
1658 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001659 return Parse('E');
1660 }
1661 }
Jason Molenda026aa492014-10-15 22:11:15 +00001662
Kate Stonee2b21862014-07-22 17:03:38 +00001663 // <unresolved-type> ::= <template-param>
1664 // ::= <decltype>
1665 // ::= <substitution>
Jason Molenda026aa492014-10-15 22:11:15 +00001666
1667 bool
1668 ParseUnresolvedType()
Kate Stonee2b21862014-07-22 17:03:38 +00001669 {
1670 int type_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001671 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001672 {
1673 case 'T':
Jason Molenda026aa492014-10-15 22:11:15 +00001674 if (!ParseTemplateParam())
1675 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001676 EndSubstitution(type_start_cookie);
1677 return true;
1678 case 'S':
1679 {
Jason Molenda026aa492014-10-15 22:11:15 +00001680 if (*m_read_ptr != 't')
1681 return ParseSubstitution();
1682
1683 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001684 WriteStdPrefix();
1685 NameState type_name = {};
Jason Molenda026aa492014-10-15 22:11:15 +00001686 if (!ParseUnqualifiedName(type_name))
1687 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001688 EndSubstitution(type_start_cookie);
1689 return true;
Jason Molenda026aa492014-10-15 22:11:15 +00001690
Kate Stonee2b21862014-07-22 17:03:38 +00001691 }
1692 case 'D':
1693 default:
1694#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001695 printf("*** Unsupported unqualified type: %3s\n", m_read_ptr - 1);
Kate Stonee2b21862014-07-22 17:03:38 +00001696#endif
1697 return false;
1698 }
1699 }
Jason Molenda026aa492014-10-15 22:11:15 +00001700
Kate Stonee2b21862014-07-22 17:03:38 +00001701 // <base-unresolved-name> ::= <simple-id> # unresolved name
1702 // extension ::= <operator-name> # unresolved operator-function-id
1703 // extension ::= <operator-name> <template-args> # unresolved operator template-id
1704 // ::= on <operator-name> # unresolved operator-function-id
1705 // ::= on <operator-name> <template-args> # unresolved operator template-id
1706 // ::= dn <destructor-name> # destructor or pseudo-destructor;
1707 // # e.g. ~X or ~X<N-1>
Jason Molenda026aa492014-10-15 22:11:15 +00001708
1709 bool
1710 ParseBaseUnresolvedName()
Kate Stonee2b21862014-07-22 17:03:38 +00001711 {
1712#ifdef DEBUG_FAILURES
1713 printf("*** Base unresolved name unsupported\n");
1714#endif
1715 return false;
1716 }
Jason Molenda026aa492014-10-15 22:11:15 +00001717
Kate Stonee2b21862014-07-22 17:03:38 +00001718 // <unresolved-name>
1719 // extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
1720 // ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
1721 // ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
1722 // # A::x, N::y, A<T>::z; "gs" means leading "::"
1723 // ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
1724 // extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
1725 // # T::N::x /decltype(p)::N::x
1726 // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001727
1728 bool
1729 ParseUnresolvedName()
Kate Stonee2b21862014-07-22 17:03:38 +00001730 {
1731#ifdef DEBUG_FAILURES
1732 printf("*** Unresolved names not supported\n");
1733#endif
1734 //TODO: grammar for all of this seems unclear...
1735 return false;
Jason Molenda026aa492014-10-15 22:11:15 +00001736
Jason Molenda61e0a3e2014-10-17 01:36:20 +00001737#if 0 // TODO
Jason Molenda026aa492014-10-15 22:11:15 +00001738 if (*m_read_ptr == 'g' && *(m_read_ptr + 1) == 's')
Kate Stonee2b21862014-07-22 17:03:38 +00001739 {
Jason Molenda026aa492014-10-15 22:11:15 +00001740 m_read_ptr += 2;
Kate Stonee2b21862014-07-22 17:03:38 +00001741 WriteNamespaceSeparator();
1742 }
Jason Molenda61e0a3e2014-10-17 01:36:20 +00001743#endif // TODO
Kate Stonee2b21862014-07-22 17:03:38 +00001744 }
Jason Molenda026aa492014-10-15 22:11:15 +00001745
Kate Stonee2b21862014-07-22 17:03:38 +00001746 // <expression> ::= <unary operator-name> <expression>
1747 // ::= <binary operator-name> <expression> <expression>
1748 // ::= <ternary operator-name> <expression> <expression> <expression>
1749 // ::= cl <expression>+ E # call
1750 // ::= cv <type> <expression> # conversion with one argument
1751 // ::= cv <type> _ <expression>* E # conversion with a different number of arguments
1752 // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
1753 // ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
1754 // ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
1755 // ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1756 // ::= [gs] dl <expression> # delete expression
1757 // ::= [gs] da <expression> # delete[] expression
1758 // ::= pp_ <expression> # prefix ++
1759 // ::= mm_ <expression> # prefix --
1760 // ::= ti <type> # typeid (type)
1761 // ::= te <expression> # typeid (expression)
1762 // ::= dc <type> <expression> # dynamic_cast<type> (expression)
1763 // ::= sc <type> <expression> # static_cast<type> (expression)
1764 // ::= cc <type> <expression> # const_cast<type> (expression)
1765 // ::= rc <type> <expression> # reinterpret_cast<type> (expression)
1766 // ::= st <type> # sizeof (a type)
1767 // ::= sz <expression> # sizeof (an expression)
1768 // ::= at <type> # alignof (a type)
1769 // ::= az <expression> # alignof (an expression)
1770 // ::= nx <expression> # noexcept (expression)
1771 // ::= <template-param>
1772 // ::= <function-param>
1773 // ::= dt <expression> <unresolved-name> # expr.name
1774 // ::= pt <expression> <unresolved-name> # expr->name
1775 // ::= ds <expression> <expression> # expr.*expr
1776 // ::= sZ <template-param> # size of a parameter pack
1777 // ::= sZ <function-param> # size of a function parameter pack
1778 // ::= sp <expression> # pack expansion
1779 // ::= tw <expression> # throw expression
1780 // ::= tr # throw with no operand (rethrow)
1781 // ::= <unresolved-name> # f(p), N::f(p), ::f(p),
1782 // # freestanding dependent name (e.g., T::x),
1783 // # objectless nonstatic member reference
1784 // ::= <expr-primary>
Jason Molenda026aa492014-10-15 22:11:15 +00001785
1786 bool
1787 ParseExpression()
Kate Stonee2b21862014-07-22 17:03:38 +00001788 {
1789 Operator expression_operator = TryParseOperator();
1790 switch (expression_operator.kind)
1791 {
1792 case OperatorKind::Unary:
1793 Write(expression_operator.name);
1794 Write('(');
Jason Molenda026aa492014-10-15 22:11:15 +00001795 if (!ParseExpression())
1796 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001797 Write(')');
1798 return true;
1799 case OperatorKind::Binary:
Jason Molenda026aa492014-10-15 22:11:15 +00001800 if (!ParseExpression())
1801 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001802 Write(expression_operator.name);
1803 return ParseExpression();
1804 case OperatorKind::Ternary:
Jason Molenda026aa492014-10-15 22:11:15 +00001805 if (!ParseExpression())
1806 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001807 Write('?');
Jason Molenda026aa492014-10-15 22:11:15 +00001808 if (!ParseExpression())
1809 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001810 Write(':');
1811 return ParseExpression();
1812 case OperatorKind::NoMatch:
1813 break;
1814 case OperatorKind::Other:
1815 default:
1816#ifdef DEBUG_FAILURES
1817 printf("*** Unsupported operator: %s\n", expression_operator.name);
1818#endif
1819 return false;
1820 }
Jason Molenda026aa492014-10-15 22:11:15 +00001821
1822 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001823 {
1824 case 'T': return ParseTemplateParam();
1825 case 'L': return ParseExpressionPrimary();
1826 case 's':
Jason Molenda026aa492014-10-15 22:11:15 +00001827 if (*m_read_ptr++ == 'r')
1828 return ParseUnresolvedName();
1829 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001830 // fallthrough
1831 default:
1832 return ParseExpressionPrimary();
1833 }
1834 }
Jason Molenda026aa492014-10-15 22:11:15 +00001835
Kate Stonee2b21862014-07-22 17:03:38 +00001836 // <template-arg> ::= <type> # type or template
1837 // ::= X <expression> E # expression
1838 // ::= <expr-primary> # simple expressions
1839 // ::= J <template-arg>* E # argument pack
1840 // ::= LZ <encoding> E # extension
Jason Molenda026aa492014-10-15 22:11:15 +00001841
1842 bool
1843 ParseTemplateArg()
Kate Stonee2b21862014-07-22 17:03:38 +00001844 {
Jason Molenda026aa492014-10-15 22:11:15 +00001845 switch (*m_read_ptr) {
Kate Stonee2b21862014-07-22 17:03:38 +00001846 case 'J':
1847#ifdef DEBUG_FAILURES
1848 printf("*** Template argument packs unsupported\n");
1849#endif
1850 return false;
1851 case 'X':
Jason Molenda026aa492014-10-15 22:11:15 +00001852 ++m_read_ptr;
1853 if (!ParseExpression())
1854 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001855 return Parse('E');
1856 case 'L':
Jason Molenda026aa492014-10-15 22:11:15 +00001857 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001858 return ParseExpressionPrimary();
1859 default:
1860 return ParseType();
1861 }
1862 }
Jason Molenda026aa492014-10-15 22:11:15 +00001863
Kate Stonee2b21862014-07-22 17:03:38 +00001864 // <template-args> ::= I <template-arg>* E
1865 // extension, the abi says <template-arg>+
Jason Molenda026aa492014-10-15 22:11:15 +00001866
1867 bool
1868 ParseTemplateArgs(bool record_template_args = false)
Kate Stonee2b21862014-07-22 17:03:38 +00001869 {
Jason Molenda026aa492014-10-15 22:11:15 +00001870 if (record_template_args)
1871 ResetTemplateArgs();
1872
Kate Stonee2b21862014-07-22 17:03:38 +00001873 bool first_arg = true;
Jason Molenda026aa492014-10-15 22:11:15 +00001874 while (*m_read_ptr != 'E')
Kate Stonee2b21862014-07-22 17:03:38 +00001875 {
Jason Molenda026aa492014-10-15 22:11:15 +00001876 if (first_arg)
1877 first_arg = false;
Kate Stonee2b21862014-07-22 17:03:38 +00001878 else WriteCommaSpace();
Jason Molenda026aa492014-10-15 22:11:15 +00001879
Kate Stonee2b21862014-07-22 17:03:38 +00001880 int template_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001881 if (!ParseTemplateArg())
1882 return false;
1883 if (record_template_args)
1884 EndTemplateArg(template_start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001885 }
Jason Molenda026aa492014-10-15 22:11:15 +00001886 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001887 return true;
1888 }
Jason Molenda026aa492014-10-15 22:11:15 +00001889
Kate Stonee2b21862014-07-22 17:03:38 +00001890 // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
1891 // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
1892 //
1893 // <prefix> ::= <prefix> <unqualified-name>
1894 // ::= <template-prefix> <template-args>
1895 // ::= <template-param>
1896 // ::= <decltype>
1897 // ::= # empty
1898 // ::= <substitution>
1899 // ::= <prefix> <data-member-prefix>
1900 // extension ::= L
1901 //
1902 // <template-prefix> ::= <prefix> <template unqualified-name>
1903 // ::= <template-param>
1904 // ::= <substitution>
1905 //
1906 // <unqualified-name> ::= <operator-name>
1907 // ::= <ctor-dtor-name>
1908 // ::= <source-name>
1909 // ::= <unnamed-type-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001910
1911 bool
1912 ParseNestedName(NameState & name_state, bool parse_discriminator = false)
Kate Stonee2b21862014-07-22 17:03:38 +00001913 {
1914 int qualifiers = TryParseQualifiers(true, true);
1915 bool first_part = true;
1916 bool suppress_substitution = true;
1917 int name_start_cookie = GetStartCookie();
1918 while (true)
1919 {
Jason Molenda026aa492014-10-15 22:11:15 +00001920 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001921 if (next == 'E')
1922 {
Jason Molenda026aa492014-10-15 22:11:15 +00001923 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001924 break;
1925 }
Jason Molenda026aa492014-10-15 22:11:15 +00001926
Kate Stonee2b21862014-07-22 17:03:38 +00001927 // Record a substitution candidate for all prefixes, but not the full name
Jason Molenda026aa492014-10-15 22:11:15 +00001928 if (suppress_substitution)
1929 suppress_substitution = false;
Kate Stonee2b21862014-07-22 17:03:38 +00001930 else EndSubstitution(name_start_cookie);
Jason Molenda026aa492014-10-15 22:11:15 +00001931
Kate Stonee2b21862014-07-22 17:03:38 +00001932 if (next == 'I')
1933 {
Jason Molenda026aa492014-10-15 22:11:15 +00001934 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001935 name_state.is_last_generic = true;
1936 WriteTemplateStart();
Jason Molenda026aa492014-10-15 22:11:15 +00001937 if (!ParseTemplateArgs(name_state.parse_function_params))
1938 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001939 WriteTemplateEnd();
1940 continue;
1941 }
Jason Molenda026aa492014-10-15 22:11:15 +00001942
1943 if (first_part)
1944 first_part = false;
Kate Stonee2b21862014-07-22 17:03:38 +00001945 else WriteNamespaceSeparator();
Jason Molenda026aa492014-10-15 22:11:15 +00001946
Kate Stonee2b21862014-07-22 17:03:38 +00001947 name_state.is_last_generic = false;
1948 switch (next)
1949 {
1950 case '0':
1951 case '1':
1952 case '2':
1953 case '3':
1954 case '4':
1955 case '5':
1956 case '6':
1957 case '7':
1958 case '8':
1959 case '9':
1960 {
1961 int name_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001962 if (!ParseSourceName())
1963 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001964 name_state.last_name_range = EndRange(name_start_cookie);
1965 continue;
1966 }
1967 case 'S':
Jason Molenda026aa492014-10-15 22:11:15 +00001968 if (*++m_read_ptr == 't')
Kate Stonee2b21862014-07-22 17:03:38 +00001969 {
1970 WriteStdPrefix();
Jason Molenda026aa492014-10-15 22:11:15 +00001971 ++m_read_ptr;
1972 if (!ParseUnqualifiedName(name_state))
1973 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001974 }
1975 else
1976 {
Jason Molenda026aa492014-10-15 22:11:15 +00001977 if (!ParseSubstitution())
1978 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001979 suppress_substitution = true;
1980 }
1981 continue;
1982 case 'T':
Jason Molenda026aa492014-10-15 22:11:15 +00001983 ++m_read_ptr;
1984 if (!ParseTemplateParam())
1985 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001986 continue;
1987 case 'C':
Jason Molenda026aa492014-10-15 22:11:15 +00001988 ++m_read_ptr;
1989 if (!ParseCtor(name_state))
1990 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001991 continue;
1992 case 'D':
1993 {
Jason Molenda026aa492014-10-15 22:11:15 +00001994 switch (*(m_read_ptr + 1))
Kate Stonee2b21862014-07-22 17:03:38 +00001995 {
1996 case 't':
1997 case 'T':
1998#ifdef DEBUG_FAILURES
1999 printf("*** Decltype unsupported\n");
2000#endif
2001 return false;
2002 }
Jason Molenda026aa492014-10-15 22:11:15 +00002003 ++m_read_ptr;
2004 if (!ParseDtor(name_state))
2005 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002006 continue;
2007 }
2008 case 'U':
Jason Molenda026aa492014-10-15 22:11:15 +00002009 ++m_read_ptr;
2010 if (!ParseUnnamedTypeName(name_state))
2011 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002012 continue;
2013 case 'L':
Jason Molenda026aa492014-10-15 22:11:15 +00002014 ++m_read_ptr;
2015 if (!ParseUnqualifiedName(name_state))
2016 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002017 continue;
2018 default:
Jason Molenda026aa492014-10-15 22:11:15 +00002019 if (!ParseOperatorName(name_state))
2020 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002021 }
2022 }
Jason Molenda026aa492014-10-15 22:11:15 +00002023
2024 if (parse_discriminator)
2025 TryParseDiscriminator();
2026 if (name_state.parse_function_params
2027 && !ParseFunctionArgs(name_state, name_start_cookie))
2028 {
2029 return false;
2030 }
2031 if (qualifiers)
2032 WriteQualifiers(qualifiers);
Kate Stonee2b21862014-07-22 17:03:38 +00002033 return true;
2034 }
Jason Molenda026aa492014-10-15 22:11:15 +00002035
Kate Stonee2b21862014-07-22 17:03:38 +00002036 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2037 // := Z <function encoding> E s [<discriminator>]
2038 // := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Jason Molenda026aa492014-10-15 22:11:15 +00002039
2040 bool
2041 ParseLocalName(bool parse_function_params)
Kate Stonee2b21862014-07-22 17:03:38 +00002042 {
Jason Molenda026aa492014-10-15 22:11:15 +00002043 if (!ParseEncoding())
2044 return false;
2045 if (!Parse('E'))
2046 return false;
2047
2048 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002049 {
2050 case 's':
Kate Stone641e9f82014-12-06 01:42:41 +00002051 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002052 TryParseDiscriminator(); // Optional and ignored
2053 WRITE("::string literal");
2054 break;
2055 case 'd':
Kate Stone641e9f82014-12-06 01:42:41 +00002056 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002057 TryParseNumber(); // Optional and ignored
Kate Stone641e9f82014-12-06 01:42:41 +00002058 if (!Parse('_'))
2059 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002060 WriteNamespaceSeparator();
Jason Molenda026aa492014-10-15 22:11:15 +00002061 if (!ParseName())
2062 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002063 break;
2064 default:
2065 WriteNamespaceSeparator();
Jason Molenda026aa492014-10-15 22:11:15 +00002066 if (!ParseName(parse_function_params, true))
2067 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002068 TryParseDiscriminator(); // Optional and ignored
2069 }
2070 return true;
2071 }
Jason Molenda026aa492014-10-15 22:11:15 +00002072
Kate Stonee2b21862014-07-22 17:03:38 +00002073 // <name> ::= <nested-name>
2074 // ::= <local-name>
2075 // ::= <unscoped-template-name> <template-args>
2076 // ::= <unscoped-name>
Jason Molenda026aa492014-10-15 22:11:15 +00002077
Kate Stonee2b21862014-07-22 17:03:38 +00002078 // <unscoped-template-name> ::= <unscoped-name>
2079 // ::= <substitution>
Jason Molenda026aa492014-10-15 22:11:15 +00002080
2081 bool
2082 ParseName(bool parse_function_params = false,
Kate Stonee2b21862014-07-22 17:03:38 +00002083 bool parse_discriminator = false)
2084 {
Jason Molenda61e0a3e2014-10-17 01:36:20 +00002085 NameState name_state = { parse_function_params, false, false, {0, 0}};
Kate Stonee2b21862014-07-22 17:03:38 +00002086 int name_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00002087
2088 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002089 {
2090 case 'N':
Jason Molenda026aa492014-10-15 22:11:15 +00002091 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002092 return ParseNestedName(name_state, parse_discriminator);
2093 case 'Z':
2094 {
Jason Molenda026aa492014-10-15 22:11:15 +00002095 ++m_read_ptr;
2096 if (!ParseLocalName(parse_function_params))
2097 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002098 break;
2099 }
2100 case 'L':
Jason Molenda026aa492014-10-15 22:11:15 +00002101 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002102 // fallthrough
2103 default:
2104 {
Jason Molenda026aa492014-10-15 22:11:15 +00002105 if (!ParseUnscopedName(name_state))
2106 return false;
2107
2108 if (*m_read_ptr == 'I')
Kate Stonee2b21862014-07-22 17:03:38 +00002109 {
2110 EndSubstitution(name_start_cookie);
Jason Molenda026aa492014-10-15 22:11:15 +00002111
2112 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002113 name_state.is_last_generic = true;
2114 WriteTemplateStart();
Jason Molenda026aa492014-10-15 22:11:15 +00002115 if (!ParseTemplateArgs(parse_function_params))
2116 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002117 WriteTemplateEnd();
2118 }
2119 break;
2120 }
2121 }
Jason Molenda026aa492014-10-15 22:11:15 +00002122 if (parse_discriminator)
2123 TryParseDiscriminator();
Kate Stonee2b21862014-07-22 17:03:38 +00002124 if (parse_function_params &&
Jason Molenda026aa492014-10-15 22:11:15 +00002125 !ParseFunctionArgs(name_state, name_start_cookie))
2126 {
2127 return false;
2128 }
Kate Stonee2b21862014-07-22 17:03:38 +00002129 return true;
2130 }
Jason Molenda026aa492014-10-15 22:11:15 +00002131
Kate Stonee2b21862014-07-22 17:03:38 +00002132 // <call-offset> ::= h <nv-offset> _
2133 // ::= v <v-offset> _
2134 //
2135 // <nv-offset> ::= <offset number>
2136 // # non-virtual base override
2137 //
2138 // <v-offset> ::= <offset number> _ <virtual offset number>
2139 // # virtual base override, with vcall offset
Jason Molenda026aa492014-10-15 22:11:15 +00002140
2141 bool
2142 ParseCallOffset()
Kate Stonee2b21862014-07-22 17:03:38 +00002143 {
Jason Molenda026aa492014-10-15 22:11:15 +00002144 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00002145 {
2146 case 'h':
Jason Molenda026aa492014-10-15 22:11:15 +00002147 if (*m_read_ptr == 'n')
2148 ++m_read_ptr;
2149 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2150 break;
Kate Stonee2b21862014-07-22 17:03:38 +00002151 return true;
2152 case 'v':
Jason Molenda026aa492014-10-15 22:11:15 +00002153 if (*m_read_ptr == 'n')
2154 ++m_read_ptr;
2155 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2156 break;
2157 if (*m_read_ptr == 'n')
2158 ++m_read_ptr;
2159 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2160 break;
Kate Stonee2b21862014-07-22 17:03:38 +00002161 return true;
2162 }
2163#ifdef DEBUG_FAILURES
2164 printf("*** Malformed call offset\n");
2165#endif
2166 return false;
2167 }
Jason Molenda026aa492014-10-15 22:11:15 +00002168
Kate Stonee2b21862014-07-22 17:03:38 +00002169 // <special-name> ::= TV <type> # virtual table
2170 // ::= TT <type> # VTT structure (construction vtable index)
2171 // ::= TI <type> # typeinfo structure
2172 // ::= TS <type> # typeinfo name (null-terminated byte string)
2173 // ::= Tc <call-offset> <call-offset> <base encoding>
2174 // # base is the nominal target function of thunk
2175 // # first call-offset is 'this' adjustment
2176 // # second call-offset is result adjustment
2177 // ::= T <call-offset> <base encoding>
2178 // # base is the nominal target function of thunk
2179 // extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
Jason Molenda026aa492014-10-15 22:11:15 +00002180
2181 bool
2182 ParseSpecialNameT()
Kate Stonee2b21862014-07-22 17:03:38 +00002183 {
Jason Molenda026aa492014-10-15 22:11:15 +00002184 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00002185 {
2186 case 'V':
2187 WRITE("vtable for ");
2188 return ParseType();
2189 case 'T':
2190 WRITE("VTT for ");
2191 return ParseType();
2192 case 'I':
2193 WRITE("typeinfo for ");
2194 return ParseType();
2195 case 'S':
2196 WRITE("typeinfo name for ");
2197 return ParseType();
2198 case 'c':
2199 case 'C':
2200#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00002201 printf("*** Unsupported thunk or construction vtable name: %.3s\n", m_read_ptr - 1);
Kate Stonee2b21862014-07-22 17:03:38 +00002202#endif
2203 return false;
2204 default:
Jason Molenda026aa492014-10-15 22:11:15 +00002205 if (*--m_read_ptr == 'v')
Kate Stonee2b21862014-07-22 17:03:38 +00002206 {
2207 WRITE("virtual thunk to ");
2208 }
2209 else
2210 {
2211 WRITE("non-virtual thunk to ");
2212 }
Jason Molenda026aa492014-10-15 22:11:15 +00002213 if (!ParseCallOffset())
2214 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002215 return ParseEncoding();
2216 }
2217 }
Jason Molenda026aa492014-10-15 22:11:15 +00002218
Kate Stonee2b21862014-07-22 17:03:38 +00002219 // <special-name> ::= GV <object name> # Guard variable for one-time initialization
2220 // # No <type>
2221 // extension ::= GR <object name> # reference temporary for object
Jason Molenda026aa492014-10-15 22:11:15 +00002222
2223 bool
2224 ParseSpecialNameG()
Kate Stonee2b21862014-07-22 17:03:38 +00002225 {
Jason Molenda026aa492014-10-15 22:11:15 +00002226 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00002227 {
2228 case 'V':
2229 WRITE("guard variable for ");
Jason Molenda026aa492014-10-15 22:11:15 +00002230 if (!ParseName(true))
2231 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002232 break;
2233 case 'R':
2234 WRITE("reference temporary for ");
Jason Molenda026aa492014-10-15 22:11:15 +00002235 if (!ParseName(true))
2236 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002237 break;
2238 default:
2239#ifdef DEBUG_FAILURES
2240 printf("*** Unknown G encoding\n");
2241#endif
2242 return false;
2243 }
2244 return true;
2245 }
Jason Molenda026aa492014-10-15 22:11:15 +00002246
Kate Stonee2b21862014-07-22 17:03:38 +00002247 // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types
Jason Molenda026aa492014-10-15 22:11:15 +00002248
2249 bool
2250 ParseFunctionArgs(NameState & name_state, int return_insert_cookie)
Kate Stonee2b21862014-07-22 17:03:38 +00002251 {
Jason Molenda026aa492014-10-15 22:11:15 +00002252 char next = *m_read_ptr;
2253 if (next == 'E' || next == '\0' || next == '.')
2254 return true;
2255
Kate Stonee2b21862014-07-22 17:03:38 +00002256 // Clang has a bad habit of making unique manglings by just sticking numbers on the end of a symbol,
2257 // which is ambiguous with malformed source name manglings
Jason Molenda026aa492014-10-15 22:11:15 +00002258 const char *before_clang_uniquing_test = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002259 if (TryParseNumber())
2260 {
Jason Molenda026aa492014-10-15 22:11:15 +00002261 if (*m_read_ptr == '\0')
2262 return true;
2263 m_read_ptr = before_clang_uniquing_test;
Kate Stonee2b21862014-07-22 17:03:38 +00002264 }
Jason Molenda026aa492014-10-15 22:11:15 +00002265
Kate Stonee2b21862014-07-22 17:03:38 +00002266 if (name_state.is_last_generic && !name_state.has_no_return_type)
2267 {
2268 int return_type_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00002269 if (!ParseType())
2270 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002271 Write(' ');
2272 ReorderRange(EndRange(return_type_start_cookie),
2273 return_insert_cookie);
2274 }
Jason Molenda026aa492014-10-15 22:11:15 +00002275
Kate Stonee2b21862014-07-22 17:03:38 +00002276 Write('(');
2277 bool first_param = true;
2278 while (true)
2279 {
Jason Molenda026aa492014-10-15 22:11:15 +00002280 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002281 {
2282 case '\0':
2283 case 'E':
2284 case '.':
2285 break;
2286 case 'v':
Jason Molenda026aa492014-10-15 22:11:15 +00002287 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002288 continue;
2289 case '_':
2290 // Not a formal part of the mangling specification, but clang emits suffixes starting with _block_invoke
Jason Molenda026aa492014-10-15 22:11:15 +00002291 if (strncmp(m_read_ptr, "_block_invoke", 13) == 0)
Kate Stonee2b21862014-07-22 17:03:38 +00002292 {
Jason Molenda026aa492014-10-15 22:11:15 +00002293 m_read_ptr += strlen(m_read_ptr);
Kate Stonee2b21862014-07-22 17:03:38 +00002294 break;
2295 }
2296 // fallthrough
2297 default:
Jason Molenda026aa492014-10-15 22:11:15 +00002298 if (first_param)
2299 first_param = false;
Kate Stonee2b21862014-07-22 17:03:38 +00002300 else WriteCommaSpace();
Jason Molenda026aa492014-10-15 22:11:15 +00002301
2302 if (!ParseType())
2303 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002304 continue;
2305 }
2306 break;
2307 }
2308 Write(')');
2309 return true;
2310 }
Jason Molenda026aa492014-10-15 22:11:15 +00002311
Kate Stonee2b21862014-07-22 17:03:38 +00002312 // <encoding> ::= <function name> <bare-function-type>
2313 // ::= <data name>
2314 // ::= <special-name>
Jason Molenda026aa492014-10-15 22:11:15 +00002315
2316 bool
2317 ParseEncoding()
Kate Stonee2b21862014-07-22 17:03:38 +00002318 {
Jason Molenda026aa492014-10-15 22:11:15 +00002319 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002320 {
2321 case 'T':
Jason Molenda026aa492014-10-15 22:11:15 +00002322 ++m_read_ptr;
2323 if (!ParseSpecialNameT())
2324 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002325 break;
2326 case 'G':
Jason Molenda026aa492014-10-15 22:11:15 +00002327 ++m_read_ptr;
2328 if (!ParseSpecialNameG())
2329 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002330 break;
2331 default:
Jason Molenda026aa492014-10-15 22:11:15 +00002332 if (!ParseName(true))
2333 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002334 break;
2335 }
2336 return true;
2337 }
Jason Molenda026aa492014-10-15 22:11:15 +00002338
2339 bool
2340 ParseMangling(const char *mangled_name, long mangled_name_length = 0)
Kate Stonee2b21862014-07-22 17:03:38 +00002341 {
Jason Molenda026aa492014-10-15 22:11:15 +00002342 if (!mangled_name_length)
2343 mangled_name_length = strlen(mangled_name);
2344 m_read_end = mangled_name + mangled_name_length;
2345 m_read_ptr = mangled_name;
2346 m_write_ptr = m_buffer;
2347 m_next_substitute_index = 0;
2348 m_next_template_arg_index = m_rewrite_ranges_size - 1;
2349
2350 if (*m_read_ptr++ != '_' || *m_read_ptr++ != 'Z')
Kate Stonee2b21862014-07-22 17:03:38 +00002351 {
2352#ifdef DEBUG_FAILURES
2353 printf("*** Missing _Z prefix\n");
2354#endif
2355 return false;
2356 }
Jason Molenda026aa492014-10-15 22:11:15 +00002357 if (!ParseEncoding())
2358 return false;
2359 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002360 {
2361 case '.':
2362 Write(' ');
2363 Write('(');
Jason Molenda026aa492014-10-15 22:11:15 +00002364 Write(m_read_ptr, m_read_end - m_read_ptr);
Kate Stonee2b21862014-07-22 17:03:38 +00002365 Write(')');
2366 case '\0':
2367 return true;
2368 default:
2369#ifdef DEBUG_FAILURES
2370 printf("*** Unparsed mangled content\n");
2371#endif
2372 return false;
2373 }
2374 }
Jason Molenda026aa492014-10-15 22:11:15 +00002375
Kate Stonee2b21862014-07-22 17:03:38 +00002376private:
Jason Molenda026aa492014-10-15 22:11:15 +00002377
Kate Stonee2b21862014-07-22 17:03:38 +00002378 // External scratch storage used during demanglings
Jason Molenda026aa492014-10-15 22:11:15 +00002379
2380 char *m_buffer;
2381 const char *m_buffer_end;
2382 BufferRange *m_rewrite_ranges;
2383 int m_rewrite_ranges_size;
2384 bool m_owns_buffer;
2385 bool m_owns_m_rewrite_ranges;
2386
Kate Stonee2b21862014-07-22 17:03:38 +00002387 // Internal state used during demangling
Jason Molenda026aa492014-10-15 22:11:15 +00002388
2389 const char *m_read_ptr;
2390 const char *m_read_end;
2391 char *m_write_ptr;
2392 int m_next_template_arg_index;
2393 int m_next_substitute_index;
Kate Stonee2b21862014-07-22 17:03:38 +00002394};
2395
2396} // Anonymous namespace
2397
2398// Public entry points referenced from Mangled.cpp
2399namespace lldb_private
2400{
Jason Molenda026aa492014-10-15 22:11:15 +00002401 char *
2402 FastDemangle(const char *mangled_name)
Kate Stonee2b21862014-07-22 17:03:38 +00002403 {
2404 char buffer[16384];
Jason Molenda026aa492014-10-15 22:11:15 +00002405 SymbolDemangler demangler(buffer, sizeof (buffer));
Kate Stonee2b21862014-07-22 17:03:38 +00002406 return demangler.GetDemangledCopy(mangled_name);
2407 }
2408
Jason Molenda026aa492014-10-15 22:11:15 +00002409 char *
2410 FastDemangle(const char *mangled_name, long mangled_name_length)
Kate Stonee2b21862014-07-22 17:03:38 +00002411 {
2412 char buffer[16384];
Jason Molenda026aa492014-10-15 22:11:15 +00002413 SymbolDemangler demangler(buffer, sizeof (buffer));
Kate Stonee2b21862014-07-22 17:03:38 +00002414 return demangler.GetDemangledCopy(mangled_name, mangled_name_length);
2415 }
2416} // lldb_private namespace