blob: a965c0e3fd1190d5754d0739a2a0ba7d3144b1a0 [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 Molenda026aa492014-10-15 22:11:15 +0000386 GrowBuffer(end_m_write_ptr - m_buffer_end);
387 end_m_write_ptr = m_write_ptr + content_length;
Kate Stonee2b21862014-07-22 17:03:38 +0000388 }
Jason Molenda026aa492014-10-15 22:11:15 +0000389 memcpy(m_write_ptr, content, content_length);
390 m_write_ptr = end_m_write_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000391 }
Jason Molenda026aa492014-10-15 22:11:15 +0000392#define WRITE(x) Write(x, sizeof (x) - 1)
393
394 void
395 WriteTemplateStart()
Kate Stonee2b21862014-07-22 17:03:38 +0000396 {
397 Write('<');
398 }
Jason Molenda026aa492014-10-15 22:11:15 +0000399
400 void
401 WriteTemplateEnd()
Kate Stonee2b21862014-07-22 17:03:38 +0000402 {
403 // Put a space between terminal > characters when nesting templates
Jason Molenda026aa492014-10-15 22:11:15 +0000404 if (m_write_ptr != m_buffer && *(m_write_ptr - 1) == '>')
405 WRITE(" >");
Kate Stonee2b21862014-07-22 17:03:38 +0000406 else Write('>');
407 }
Jason Molenda026aa492014-10-15 22:11:15 +0000408
409 void
410 WriteCommaSpace()
Kate Stonee2b21862014-07-22 17:03:38 +0000411 {
412 WRITE(", ");
413 }
Jason Molenda026aa492014-10-15 22:11:15 +0000414
415 void
416 WriteNamespaceSeparator()
Kate Stonee2b21862014-07-22 17:03:38 +0000417 {
418 WRITE("::");
419 }
Jason Molenda026aa492014-10-15 22:11:15 +0000420
421 void
422 WriteStdPrefix()
Kate Stonee2b21862014-07-22 17:03:38 +0000423 {
424 WRITE("std::");
425 }
Jason Molenda026aa492014-10-15 22:11:15 +0000426
427 void
428 WriteQualifiers(int qualifiers, bool space_before_reference = true)
Kate Stonee2b21862014-07-22 17:03:38 +0000429 {
Jason Molenda026aa492014-10-15 22:11:15 +0000430 if (qualifiers & QualifierPointer)
431 Write('*');
432 if (qualifiers & QualifierConst)
433 WRITE(" const");
434 if (qualifiers & QualifierVolatile)
435 WRITE(" volatile");
436 if (qualifiers & QualifierRestrict)
437 WRITE(" restrict");
Kate Stonee2b21862014-07-22 17:03:38 +0000438 if (qualifiers & QualifierReference)
439 {
Jason Molenda026aa492014-10-15 22:11:15 +0000440 if (space_before_reference)
441 WRITE(" &");
Kate Stonee2b21862014-07-22 17:03:38 +0000442 else Write('&');
443 }
444 if (qualifiers & QualifierRValueReference)
445 {
Jason Molenda026aa492014-10-15 22:11:15 +0000446 if (space_before_reference)
447 WRITE(" &&");
Kate Stonee2b21862014-07-22 17:03:38 +0000448 else WRITE("&&");
449 }
450 }
Jason Molenda026aa492014-10-15 22:11:15 +0000451
Kate Stonee2b21862014-07-22 17:03:38 +0000452 //----------------------------------------------------
453 // Rewrite methods
454 //
455 // Write another copy of content already present
456 // earlier in the output buffer
457 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000458
459 void
460 RewriteRange(BufferRange range)
Kate Stonee2b21862014-07-22 17:03:38 +0000461 {
Jason Molenda026aa492014-10-15 22:11:15 +0000462 Write(m_buffer + range.offset, range.length);
Kate Stonee2b21862014-07-22 17:03:38 +0000463 }
Jason Molenda026aa492014-10-15 22:11:15 +0000464
465 bool
466 RewriteSubstitution(int index)
Kate Stonee2b21862014-07-22 17:03:38 +0000467 {
Jason Molenda026aa492014-10-15 22:11:15 +0000468 if (index < 0 || index >= m_next_substitute_index)
Kate Stonee2b21862014-07-22 17:03:38 +0000469 {
470#ifdef DEBUG_FAILURES
471 printf("*** Invalid substitution #%d\n", index);
472#endif
473 return false;
474 }
Jason Molenda026aa492014-10-15 22:11:15 +0000475 RewriteRange(m_rewrite_ranges[index]);
Kate Stonee2b21862014-07-22 17:03:38 +0000476 return true;
477 }
Jason Molenda026aa492014-10-15 22:11:15 +0000478
479 bool
480 RewriteTemplateArg(int template_index)
Kate Stonee2b21862014-07-22 17:03:38 +0000481 {
Jason Molenda026aa492014-10-15 22:11:15 +0000482 int index = m_rewrite_ranges_size - 1 - template_index;
483 if (template_index < 0 || index <= m_next_template_arg_index)
Kate Stonee2b21862014-07-22 17:03:38 +0000484 {
485#ifdef DEBUG_FAILURES
486 printf("*** Invalid template arg reference #%d\n", template_index);
487#endif
488 return false;
489 }
Jason Molenda026aa492014-10-15 22:11:15 +0000490 RewriteRange(m_rewrite_ranges[index]);
Kate Stonee2b21862014-07-22 17:03:38 +0000491 return true;
492 }
Jason Molenda026aa492014-10-15 22:11:15 +0000493
Kate Stonee2b21862014-07-22 17:03:38 +0000494 //----------------------------------------------------
495 // TryParse methods
496 //
497 // Provide information with return values instead of
498 // writing to the output buffer
499 //
500 // Values indicating failure guarantee that the pre-
Jason Molenda026aa492014-10-15 22:11:15 +0000501 // call m_read_ptr is unchanged
Kate Stonee2b21862014-07-22 17:03:38 +0000502 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000503
504 int
505 TryParseNumber()
Kate Stonee2b21862014-07-22 17:03:38 +0000506 {
Jason Molenda026aa492014-10-15 22:11:15 +0000507 unsigned char digit = *m_read_ptr - '0';
508 if (digit > 9)
509 return -1;
510
Kate Stonee2b21862014-07-22 17:03:38 +0000511 int count = digit;
512 while (true)
513 {
Jason Molenda026aa492014-10-15 22:11:15 +0000514 digit = *++m_read_ptr - '0';
515 if (digit > 9)
516 break;
517
Kate Stonee2b21862014-07-22 17:03:38 +0000518 count = count * 10 + digit;
519 }
520 return count;
521 }
Jason Molenda026aa492014-10-15 22:11:15 +0000522
523 int
524 TryParseBase36Number()
Kate Stonee2b21862014-07-22 17:03:38 +0000525 {
Jason Molenda026aa492014-10-15 22:11:15 +0000526 char digit = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000527 int count;
Jason Molenda026aa492014-10-15 22:11:15 +0000528 if (digit >= '0' && digit <= '9')
529 count = digit -= '0';
530 else if (digit >= 'A' && digit <= 'Z')
531 count = digit -= ('A' - 10);
Kate Stonee2b21862014-07-22 17:03:38 +0000532 else return -1;
Jason Molenda026aa492014-10-15 22:11:15 +0000533
Kate Stonee2b21862014-07-22 17:03:38 +0000534 while (true)
535 {
Jason Molenda026aa492014-10-15 22:11:15 +0000536 digit = *++m_read_ptr;
537 if (digit >= '0' && digit <= '9')
538 digit -= '0';
539 else if (digit >= 'A' && digit <= 'Z')
540 digit -= ('A' - 10);
Kate Stonee2b21862014-07-22 17:03:38 +0000541 else break;
Jason Molenda026aa492014-10-15 22:11:15 +0000542
Kate Stonee2b21862014-07-22 17:03:38 +0000543 count = count * 36 + digit;
544 }
545 return count;
546 }
Jason Molenda026aa492014-10-15 22:11:15 +0000547
Kate Stonee2b21862014-07-22 17:03:38 +0000548 // <builtin-type> ::= v # void
549 // ::= w # wchar_t
550 // ::= b # bool
551 // ::= c # char
552 // ::= a # signed char
553 // ::= h # unsigned char
554 // ::= s # short
555 // ::= t # unsigned short
556 // ::= i # int
557 // ::= j # unsigned int
558 // ::= l # long
559 // ::= m # unsigned long
560 // ::= x # long long, __int64
561 // ::= y # unsigned long long, __int64
562 // ::= n # __int128
563 // ::= o # unsigned __int128
564 // ::= f # float
565 // ::= d # double
566 // ::= e # long double, __float80
567 // ::= g # __float128
568 // ::= z # ellipsis
569 // ::= Dd # IEEE 754r decimal floating point (64 bits)
570 // ::= De # IEEE 754r decimal floating point (128 bits)
571 // ::= Df # IEEE 754r decimal floating point (32 bits)
572 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
573 // ::= Di # char32_t
574 // ::= Ds # char16_t
575 // ::= Da # auto (in dependent new-expressions)
576 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
577 // ::= u <source-name> # vendor extended type
Jason Molenda026aa492014-10-15 22:11:15 +0000578
579 const char *
580 TryParseBuiltinType()
Kate Stonee2b21862014-07-22 17:03:38 +0000581 {
Jason Molenda026aa492014-10-15 22:11:15 +0000582 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000583 {
584 case 'v': return "void";
585 case 'w': return "wchar_t";
586 case 'b': return "bool";
587 case 'c': return "char";
588 case 'a': return "signed char";
589 case 'h': return "unsigned char";
590 case 's': return "short";
591 case 't': return "unsigned short";
592 case 'i': return "int";
593 case 'j': return "unsigned int";
594 case 'l': return "long";
595 case 'm': return "unsigned long";
596 case 'x': return "long long";
597 case 'y': return "unsigned long long";
598 case 'n': return "__int128";
599 case 'o': return "unsigned __int128";
600 case 'f': return "float";
601 case 'd': return "double";
602 case 'e': return "long double";
603 case 'g': return "__float128";
604 case 'z': return "...";
605 case 'D':
606 {
Jason Molenda026aa492014-10-15 22:11:15 +0000607 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000608 {
609 case 'd': return "decimal64";
610 case 'e': return "decimal128";
611 case 'f': return "decimal32";
612 case 'h': return "decimal16";
613 case 'i': return "char32_t";
614 case 's': return "char16_t";
615 case 'a': return "auto";
616 case 'c': return "decltype(auto)";
617 case 'n': return "std::nullptr_t";
618 default:
Jason Molenda026aa492014-10-15 22:11:15 +0000619 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000620 }
621 }
622 }
Jason Molenda026aa492014-10-15 22:11:15 +0000623 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000624 return nullptr;
625 }
Jason Molenda026aa492014-10-15 22:11:15 +0000626
Kate Stonee2b21862014-07-22 17:03:38 +0000627 // <operator-name>
628 // ::= aa # &&
629 // ::= ad # & (unary)
630 // ::= an # &
631 // ::= aN # &=
632 // ::= aS # =
633 // ::= cl # ()
634 // ::= cm # ,
635 // ::= co # ~
636 // ::= da # delete[]
637 // ::= de # * (unary)
638 // ::= dl # delete
639 // ::= dv # /
640 // ::= dV # /=
641 // ::= eo # ^
642 // ::= eO # ^=
643 // ::= eq # ==
644 // ::= ge # >=
645 // ::= gt # >
646 // ::= ix # []
647 // ::= le # <=
648 // ::= ls # <<
649 // ::= lS # <<=
650 // ::= lt # <
651 // ::= mi # -
652 // ::= mI # -=
653 // ::= ml # *
654 // ::= mL # *=
655 // ::= mm # -- (postfix in <expression> context)
656 // ::= na # new[]
657 // ::= ne # !=
658 // ::= ng # - (unary)
659 // ::= nt # !
660 // ::= nw # new
661 // ::= oo # ||
662 // ::= or # |
663 // ::= oR # |=
664 // ::= pm # ->*
665 // ::= pl # +
666 // ::= pL # +=
667 // ::= pp # ++ (postfix in <expression> context)
668 // ::= ps # + (unary)
669 // ::= pt # ->
670 // ::= qu # ?
671 // ::= rm # %
672 // ::= rM # %=
673 // ::= rs # >>
674 // ::= rS # >>=
675 // ::= cv <type> # (cast)
676 // ::= v <digit> <source-name> # vendor extended operator
Jason Molenda026aa492014-10-15 22:11:15 +0000677
678 Operator
679 TryParseOperator()
Kate Stonee2b21862014-07-22 17:03:38 +0000680 {
Jason Molenda026aa492014-10-15 22:11:15 +0000681 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000682 {
683 case 'a':
Jason Molenda026aa492014-10-15 22:11:15 +0000684 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000685 {
686 case 'a': return { "&&", OperatorKind::Binary };
687 case 'd': return { "&", OperatorKind::Unary };
688 case 'n': return { "&", OperatorKind::Binary };
689 case 'N': return { "&=", OperatorKind::Binary };
690 case 'S': return { "=", OperatorKind::Binary };
691 }
Jason Molenda026aa492014-10-15 22:11:15 +0000692 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000693 break;
694 case 'c':
Jason Molenda026aa492014-10-15 22:11:15 +0000695 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000696 {
697 case 'l': return { "()", OperatorKind::Other };
698 case 'm': return { ",", OperatorKind::Other };
699 case 'o': return { "~", OperatorKind::Unary };
700 case 'v': return { nullptr, OperatorKind::ConversionOperator };
701 }
Jason Molenda026aa492014-10-15 22:11:15 +0000702 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000703 break;
704 case 'd':
Jason Molenda026aa492014-10-15 22:11:15 +0000705 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000706 {
707 case 'a': return { " delete[]", OperatorKind::Other };
708 case 'e': return { "*", OperatorKind::Unary };
709 case 'l': return { " delete", OperatorKind::Other };
710 case 'v': return { "/", OperatorKind::Binary };
711 case 'V': return { "/=", OperatorKind::Binary };
712 }
Jason Molenda026aa492014-10-15 22:11:15 +0000713 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000714 break;
715 case 'e':
Jason Molenda026aa492014-10-15 22:11:15 +0000716 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000717 {
718 case 'o': return { "^", OperatorKind::Binary };
719 case 'O': return { "^=", OperatorKind::Binary };
720 case 'q': 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 'g':
Jason Molenda026aa492014-10-15 22:11:15 +0000725 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000726 {
727 case 'e': return { ">=", OperatorKind::Binary };
728 case 't': return { ">", OperatorKind::Binary };
729 }
Jason Molenda026aa492014-10-15 22:11:15 +0000730 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000731 break;
732 case 'i':
Jason Molenda026aa492014-10-15 22:11:15 +0000733 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000734 {
735 case 'x': return { "[]", OperatorKind::Other };
736 }
Jason Molenda026aa492014-10-15 22:11:15 +0000737 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000738 break;
739 case 'l':
Jason Molenda026aa492014-10-15 22:11:15 +0000740 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000741 {
742 case 'e': return { "<=", OperatorKind::Binary };
743 case 's': return { "<<", OperatorKind::Binary };
744 case 'S': return { "<<=", OperatorKind::Binary };
745 case 't': return { "<", OperatorKind::Binary };
746 // case 'i': return { "?", OperatorKind::Binary };
747 }
Jason Molenda026aa492014-10-15 22:11:15 +0000748 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000749 break;
750 case 'm':
Jason Molenda026aa492014-10-15 22:11:15 +0000751 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000752 {
753 case 'i': return { "-", OperatorKind::Binary };
754 case 'I': return { "-=", OperatorKind::Binary };
755 case 'l': return { "*", OperatorKind::Binary };
756 case 'L': return { "*=", OperatorKind::Binary };
757 case 'm': return { "--", OperatorKind::Postfix };
758 }
Jason Molenda026aa492014-10-15 22:11:15 +0000759 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000760 break;
761 case 'n':
Jason Molenda026aa492014-10-15 22:11:15 +0000762 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000763 {
764 case 'a': return { " new[]", OperatorKind::Other };
765 case 'e': return { "!=", OperatorKind::Binary };
766 case 'g': return { "-", OperatorKind::Unary };
767 case 't': return { "!", OperatorKind::Unary };
768 case 'w': return { " new", OperatorKind::Other };
769 }
Jason Molenda026aa492014-10-15 22:11:15 +0000770 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000771 break;
772 case 'o':
Jason Molenda026aa492014-10-15 22:11:15 +0000773 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000774 {
775 case 'o': return { "||", OperatorKind::Binary };
776 case 'r': return { "|", OperatorKind::Binary };
777 case 'R': return { "|=", OperatorKind::Binary };
778 }
Jason Molenda026aa492014-10-15 22:11:15 +0000779 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000780 break;
781 case 'p':
Jason Molenda026aa492014-10-15 22:11:15 +0000782 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000783 {
784 case 'm': return { "->*", OperatorKind::Binary };
785 case 's': return { "+", OperatorKind::Unary };
786 case 'l': return { "+", OperatorKind::Binary };
787 case 'L': return { "+=", OperatorKind::Binary };
788 case 'p': return { "++", OperatorKind::Postfix };
789 case 't': return { "->", OperatorKind::Binary };
790 }
Jason Molenda026aa492014-10-15 22:11:15 +0000791 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000792 break;
793 case 'q':
Jason Molenda026aa492014-10-15 22:11:15 +0000794 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000795 {
796 case 'u': return { "?", OperatorKind::Ternary };
797 }
Jason Molenda026aa492014-10-15 22:11:15 +0000798 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000799 break;
800 case 'r':
Jason Molenda026aa492014-10-15 22:11:15 +0000801 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000802 {
803 case 'm': return { "%", OperatorKind::Binary };
804 case 'M': return { "%=", OperatorKind::Binary };
805 case 's': return { ">>", OperatorKind::Binary };
806 case 'S': return { ">=", OperatorKind::Binary };
807 }
Jason Molenda026aa492014-10-15 22:11:15 +0000808 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000809 break;
810 case 'v':
Jason Molenda026aa492014-10-15 22:11:15 +0000811 char digit = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000812 if (digit >= '0' && digit <= '9')
813 {
Jason Molenda026aa492014-10-15 22:11:15 +0000814 m_read_ptr++;
Kate Stonee2b21862014-07-22 17:03:38 +0000815 return { nullptr, OperatorKind::Vendor };
816 }
Jason Molenda026aa492014-10-15 22:11:15 +0000817 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000818 break;
819 }
Jason Molenda026aa492014-10-15 22:11:15 +0000820 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000821 return { nullptr, OperatorKind::NoMatch };
822 }
Jason Molenda026aa492014-10-15 22:11:15 +0000823
Kate Stonee2b21862014-07-22 17:03:38 +0000824 // <CV-qualifiers> ::= [r] [V] [K]
825 // <ref-qualifier> ::= R # & ref-qualifier
826 // <ref-qualifier> ::= O # && ref-qualifier
Jason Molenda026aa492014-10-15 22:11:15 +0000827
828 int
829 TryParseQualifiers(bool allow_cv, bool allow_ro)
Kate Stonee2b21862014-07-22 17:03:38 +0000830 {
831 int qualifiers = QualifierNone;
Jason Molenda026aa492014-10-15 22:11:15 +0000832 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000833 if (allow_cv)
834 {
835 if (next == 'r') // restrict
836 {
837 qualifiers |= QualifierRestrict;
Jason Molenda026aa492014-10-15 22:11:15 +0000838 next = *++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000839 }
840 if (next == 'V') // volatile
841 {
842 qualifiers |= QualifierVolatile;
Jason Molenda026aa492014-10-15 22:11:15 +0000843 next = *++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000844 }
845 if (next == 'K') // const
846 {
847 qualifiers |= QualifierConst;
Jason Molenda026aa492014-10-15 22:11:15 +0000848 next = *++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000849 }
850 }
851 if (allow_ro)
852 {
853 if (next == 'R')
854 {
Jason Molenda026aa492014-10-15 22:11:15 +0000855 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000856 qualifiers |= QualifierReference;
857 }
858 else if (next =='O')
859 {
Jason Molenda026aa492014-10-15 22:11:15 +0000860 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000861 qualifiers |= QualifierRValueReference;
862 }
863 }
864 return qualifiers;
865 }
Jason Molenda026aa492014-10-15 22:11:15 +0000866
Kate Stonee2b21862014-07-22 17:03:38 +0000867 // <discriminator> := _ <non-negative number> # when number < 10
868 // := __ <non-negative number> _ # when number >= 10
869 // extension := decimal-digit+
Jason Molenda026aa492014-10-15 22:11:15 +0000870
871 int
872 TryParseDiscriminator()
Kate Stonee2b21862014-07-22 17:03:38 +0000873 {
Jason Molenda026aa492014-10-15 22:11:15 +0000874 const char *discriminator_start = m_read_ptr;
875
Kate Stonee2b21862014-07-22 17:03:38 +0000876 // Test the extension first, since it's what Clang uses
877 int discriminator_value = TryParseNumber();
Jason Molenda026aa492014-10-15 22:11:15 +0000878 if (discriminator_value != -1)
879 return discriminator_value;
880
881 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000882 if (next == '_')
883 {
Jason Molenda026aa492014-10-15 22:11:15 +0000884 next = *++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000885 if (next == '_')
886 {
Jason Molenda026aa492014-10-15 22:11:15 +0000887 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000888 discriminator_value = TryParseNumber();
Jason Molenda026aa492014-10-15 22:11:15 +0000889 if (discriminator_value != -1 && *m_read_ptr++ != '_')
Kate Stonee2b21862014-07-22 17:03:38 +0000890 {
891 return discriminator_value;
892 }
893 }
894 else if (next >= '0' && next <= '9')
895 {
Jason Molenda026aa492014-10-15 22:11:15 +0000896 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000897 return next - '0';
898 }
899 }
Jason Molenda026aa492014-10-15 22:11:15 +0000900
Kate Stonee2b21862014-07-22 17:03:38 +0000901 // Not a valid discriminator
Jason Molenda026aa492014-10-15 22:11:15 +0000902 m_read_ptr = discriminator_start;
Kate Stonee2b21862014-07-22 17:03:38 +0000903 return -1;
904 }
Jason Molenda026aa492014-10-15 22:11:15 +0000905
Kate Stonee2b21862014-07-22 17:03:38 +0000906 //----------------------------------------------------
907 // Parse methods
908 //
Jason Molenda026aa492014-10-15 22:11:15 +0000909 // Consume input starting from m_read_ptr and produce
910 // buffered output at m_write_ptr
Kate Stonee2b21862014-07-22 17:03:38 +0000911 //
Jason Molenda026aa492014-10-15 22:11:15 +0000912 // Failures return false and may leave m_read_ptr in an
Kate Stonee2b21862014-07-22 17:03:38 +0000913 // indeterminate state
914 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000915
916 bool
917 Parse(char character)
Kate Stonee2b21862014-07-22 17:03:38 +0000918 {
Jason Molenda026aa492014-10-15 22:11:15 +0000919 if (*m_read_ptr++ == character)
920 return true;
Kate Stonee2b21862014-07-22 17:03:38 +0000921#ifdef DEBUG_FAILURES
922 printf("*** Expected '%c'\n", character);
923#endif
924 return false;
925 }
Jason Molenda026aa492014-10-15 22:11:15 +0000926
Kate Stonee2b21862014-07-22 17:03:38 +0000927 // <number> ::= [n] <non-negative decimal integer>
Jason Molenda026aa492014-10-15 22:11:15 +0000928
929 bool
930 ParseNumber(bool allow_negative = false)
Kate Stonee2b21862014-07-22 17:03:38 +0000931 {
Jason Molenda026aa492014-10-15 22:11:15 +0000932 if (allow_negative && *m_read_ptr == 'n')
Kate Stonee2b21862014-07-22 17:03:38 +0000933 {
934 Write('-');
Jason Molenda026aa492014-10-15 22:11:15 +0000935 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000936 }
Jason Molenda026aa492014-10-15 22:11:15 +0000937 const char *before_digits = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000938 while (true)
939 {
Jason Molenda026aa492014-10-15 22:11:15 +0000940 unsigned char digit = *m_read_ptr - '0';
941 if (digit > 9)
942 break;
943 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000944 }
Jason Molenda026aa492014-10-15 22:11:15 +0000945 if (int digit_count = (int)(m_read_ptr - before_digits))
Kate Stonee2b21862014-07-22 17:03:38 +0000946 {
947 Write(before_digits, digit_count);
948 return true;
949 }
950#ifdef DEBUG_FAILURES
951 printf("*** Expected number\n");
952#endif
953 return false;
954 }
Jason Molenda026aa492014-10-15 22:11:15 +0000955
Kate Stonee2b21862014-07-22 17:03:38 +0000956 // <substitution> ::= S <seq-id> _
957 // ::= S_
958 // <substitution> ::= Sa # ::std::allocator
959 // <substitution> ::= Sb # ::std::basic_string
960 // <substitution> ::= Ss # ::std::basic_string < char,
961 // ::std::char_traits<char>,
962 // ::std::allocator<char> >
963 // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
964 // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
965 // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Jason Molenda026aa492014-10-15 22:11:15 +0000966
967 bool
968 ParseSubstitution()
Kate Stonee2b21862014-07-22 17:03:38 +0000969 {
Jason Molenda026aa492014-10-15 22:11:15 +0000970 const char *substitution;
971 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +0000972 {
973 case 'a': substitution = "std::allocator"; break;
974 case 'b': substitution = "std::basic_string"; break;
975 case 's': substitution = "std::string"; break;
976 case 'i': substitution = "std::istream"; break;
977 case 'o': substitution = "std::ostream"; break;
978 case 'd': substitution = "std::iostream"; break;
979 default:
980 // A failed attempt to parse a number will return -1 which turns out to be
981 // perfect here as S_ is the first substitution, S0_ the next and so forth
982 int substitution_index = TryParseBase36Number();
Jason Molenda026aa492014-10-15 22:11:15 +0000983 if (*m_read_ptr++ != '_')
Kate Stonee2b21862014-07-22 17:03:38 +0000984 {
985#ifdef DEBUG_FAILURES
986 printf("*** Expected terminal _ in substitution\n");
987#endif
988 return false;
989 }
Jason Molenda026aa492014-10-15 22:11:15 +0000990 return RewriteSubstitution (substitution_index + 1);
Kate Stonee2b21862014-07-22 17:03:38 +0000991 }
992 Write(substitution);
Jason Molenda026aa492014-10-15 22:11:15 +0000993 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000994 return true;
995 }
Jason Molenda026aa492014-10-15 22:11:15 +0000996
Kate Stonee2b21862014-07-22 17:03:38 +0000997 // <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
998 //
999 // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types
Jason Molenda026aa492014-10-15 22:11:15 +00001000
1001 bool
1002 ParseFunctionType (int inner_qualifiers = QualifierNone)
Kate Stonee2b21862014-07-22 17:03:38 +00001003 {
1004#ifdef DEBUG_FAILURES
1005 printf("*** Function types not supported\n");
1006#endif
1007 //TODO: first steps toward an implementation follow, but they're far
1008 // from complete. Function types tend to bracket other types eg:
1009 // int (*)() when used as the type for "name" becomes int (*name)().
1010 // This makes substitution et al ... interesting.
1011 return false;
Jason Molenda026aa492014-10-15 22:11:15 +00001012
1013 if (*m_read_ptr == 'Y')
1014 ++m_read_ptr;
1015
Kate Stonee2b21862014-07-22 17:03:38 +00001016 int return_type_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001017 if (!ParseType())
1018 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001019 Write(' ');
Jason Molenda026aa492014-10-15 22:11:15 +00001020
Kate Stonee2b21862014-07-22 17:03:38 +00001021 int insert_cookie = GetStartCookie();
1022 Write('(');
1023 bool first_param = true;
1024 int qualifiers = QualifierNone;
1025 while (true)
1026 {
Jason Molenda026aa492014-10-15 22:11:15 +00001027 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00001028 {
1029 case 'E':
Jason Molenda026aa492014-10-15 22:11:15 +00001030 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001031 Write(')');
1032 break;
1033 case 'v':
Jason Molenda026aa492014-10-15 22:11:15 +00001034 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001035 continue;
1036 case 'R':
1037 case 'O':
Jason Molenda026aa492014-10-15 22:11:15 +00001038 if (*(m_read_ptr + 1) == 'E')
Kate Stonee2b21862014-07-22 17:03:38 +00001039 {
Jason Molenda026aa492014-10-15 22:11:15 +00001040 qualifiers = TryParseQualifiers (false, true);
Kate Stonee2b21862014-07-22 17:03:38 +00001041 Parse('E');
1042 break;
1043 }
1044 // fallthrough
1045 default:
1046 {
Jason Molenda026aa492014-10-15 22:11:15 +00001047 if (first_param)
1048 first_param = false;
Kate Stonee2b21862014-07-22 17:03:38 +00001049 else WriteCommaSpace();
Jason Molenda026aa492014-10-15 22:11:15 +00001050
1051 if (!ParseType())
1052 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001053 continue;
1054 }
1055 }
1056 break;
1057 }
Jason Molenda026aa492014-10-15 22:11:15 +00001058
Kate Stonee2b21862014-07-22 17:03:38 +00001059 if (qualifiers)
1060 {
Jason Molenda026aa492014-10-15 22:11:15 +00001061 WriteQualifiers (qualifiers);
1062 EndSubstitution (return_type_start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001063 }
Jason Molenda026aa492014-10-15 22:11:15 +00001064
Kate Stonee2b21862014-07-22 17:03:38 +00001065 if (inner_qualifiers)
1066 {
1067 int qualifier_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001068 Write ('(');
1069 WriteQualifiers (inner_qualifiers);
1070 Write (')');
1071 ReorderRange (EndRange (qualifier_start_cookie), insert_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001072 }
1073 return true;
1074 }
Jason Molenda026aa492014-10-15 22:11:15 +00001075
Kate Stonee2b21862014-07-22 17:03:38 +00001076 // <array-type> ::= A <positive dimension number> _ <element type>
1077 // ::= A [<dimension expression>] _ <element type>
Jason Molenda026aa492014-10-15 22:11:15 +00001078
1079 bool
1080 ParseArrayType(int qualifiers = QualifierNone)
Kate Stonee2b21862014-07-22 17:03:38 +00001081 {
1082#ifdef DEBUG_FAILURES
1083 printf("*** Array type unsupported\n");
1084#endif
1085 //TODO: We fail horribly when recalling these as substitutions or
1086 // templates and trying to constify them eg:
1087 // _ZN4llvm2cl5applyIA28_cNS0_3optIbLb0ENS0_6parserIbEEEEEEvRKT_PT0_
1088 //
1089 //TODO: Chances are we don't do any better with references and pointers
1090 // that should be type (&) [] instead of type & []
Jason Molenda026aa492014-10-15 22:11:15 +00001091
Kate Stonee2b21862014-07-22 17:03:38 +00001092 return false;
Jason Molenda026aa492014-10-15 22:11:15 +00001093
1094 if (*m_read_ptr == '_')
Kate Stonee2b21862014-07-22 17:03:38 +00001095 {
Jason Molenda026aa492014-10-15 22:11:15 +00001096 ++m_read_ptr;
1097 if (!ParseType())
1098 return false;
1099 if (qualifiers)
1100 WriteQualifiers(qualifiers);
Kate Stonee2b21862014-07-22 17:03:38 +00001101 WRITE(" []");
1102 return true;
1103 }
1104 else
1105 {
Jason Molenda026aa492014-10-15 22:11:15 +00001106 const char *before_digits = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001107 if (TryParseNumber() != -1)
1108 {
Jason Molenda026aa492014-10-15 22:11:15 +00001109 const char *after_digits = m_read_ptr;
1110 if (!Parse('_'))
1111 return false;
1112 if (!ParseType())
1113 return false;
1114 if (qualifiers)
1115 WriteQualifiers(qualifiers);
Kate Stonee2b21862014-07-22 17:03:38 +00001116 Write(' ');
1117 Write('[');
1118 Write(before_digits, after_digits - before_digits);
1119 }
1120 else
1121 {
1122 int type_insertion_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001123 if (!ParseExpression())
1124 return false;
1125 if (!Parse('_'))
1126 return false;
1127
Kate Stonee2b21862014-07-22 17:03:38 +00001128 int type_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001129 if (!ParseType())
1130 return false;
1131 if (qualifiers)
1132 WriteQualifiers(qualifiers);
Kate Stonee2b21862014-07-22 17:03:38 +00001133 Write(' ');
1134 Write('[');
Jason Molenda026aa492014-10-15 22:11:15 +00001135 ReorderRange (EndRange (type_start_cookie), type_insertion_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001136 }
1137 Write(']');
1138 return true;
1139 }
1140 }
Jason Molenda026aa492014-10-15 22:11:15 +00001141
Kate Stonee2b21862014-07-22 17:03:38 +00001142 // <pointer-to-member-type> ::= M <class type> <member type>
Jason Molenda026aa492014-10-15 22:11:15 +00001143
Kate Stonee2b21862014-07-22 17:03:38 +00001144 //TODO: Determine how to handle pointers to function members correctly,
1145 // currently not an issue because we don't have function types at all...
Jason Molenda026aa492014-10-15 22:11:15 +00001146 bool
1147 ParsePointerToMemberType()
Kate Stonee2b21862014-07-22 17:03:38 +00001148 {
1149 int insertion_cookie = GetStartCookie();
1150 Write(' ');
Jason Molenda026aa492014-10-15 22:11:15 +00001151 if (!ParseType())
1152 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001153 WRITE("::*");
Jason Molenda026aa492014-10-15 22:11:15 +00001154
Kate Stonee2b21862014-07-22 17:03:38 +00001155 int type_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001156 if (!ParseType())
1157 return false;
1158 ReorderRange (EndRange (type_cookie), insertion_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001159 return true;
1160 }
Jason Molenda026aa492014-10-15 22:11:15 +00001161
Kate Stonee2b21862014-07-22 17:03:38 +00001162 // <template-param> ::= T_ # first template parameter
1163 // ::= T <parameter-2 non-negative number> _
Jason Molenda026aa492014-10-15 22:11:15 +00001164
1165 bool
1166 ParseTemplateParam()
Kate Stonee2b21862014-07-22 17:03:38 +00001167 {
1168 int count = TryParseNumber();
Jason Molenda026aa492014-10-15 22:11:15 +00001169 if (!Parse('_'))
1170 return false;
1171
Kate Stonee2b21862014-07-22 17:03:38 +00001172 // When no number is present we get -1, which is convenient since
1173 // T_ is the zeroth element T0_ is element 1, and so on
Jason Molenda026aa492014-10-15 22:11:15 +00001174 return RewriteTemplateArg (count + 1);
Kate Stonee2b21862014-07-22 17:03:38 +00001175 }
Jason Molenda026aa492014-10-15 22:11:15 +00001176
Kate Stonee2b21862014-07-22 17:03:38 +00001177 // <type> ::= <builtin-type>
1178 // ::= <function-type>
1179 // ::= <class-enum-type>
1180 // ::= <array-type>
1181 // ::= <pointer-to-member-type>
1182 // ::= <template-param>
1183 // ::= <template-template-param> <template-args>
1184 // ::= <decltype>
1185 // ::= <substitution>
1186 // ::= <CV-qualifiers> <type>
1187 // ::= P <type> # pointer-to
1188 // ::= R <type> # reference-to
1189 // ::= O <type> # rvalue reference-to (C++0x)
1190 // ::= C <type> # complex pair (C 2000)
1191 // ::= G <type> # imaginary (C 2000)
1192 // ::= Dp <type> # pack expansion (C++0x)
1193 // ::= U <source-name> <type> # vendor extended type qualifier
1194 // extension := U <objc-name> <objc-type> # objc-type<identifier>
1195 // extension := <vector-type> # <vector-type> starts with Dv
Jason Molenda026aa492014-10-15 22:11:15 +00001196
Kate Stonee2b21862014-07-22 17:03:38 +00001197 // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
1198 // <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001199
1200 bool
1201 ParseType()
Kate Stonee2b21862014-07-22 17:03:38 +00001202 {
1203#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001204 const char *failed_type = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001205#endif
1206 int type_start_cookie = GetStartCookie();
1207 bool suppress_substitution = false;
Jason Molenda026aa492014-10-15 22:11:15 +00001208
1209 int qualifiers = TryParseQualifiers (true, false);
1210 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00001211 {
1212 case 'D':
Jason Molenda026aa492014-10-15 22:11:15 +00001213 ++m_read_ptr;
1214 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001215 {
1216 case 'p':
Jason Molenda026aa492014-10-15 22:11:15 +00001217 if (!ParseType())
1218 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001219 break;
1220 case 'T':
1221 case 't':
1222 case 'v':
1223 default:
1224#ifdef DEBUG_FAILURES
1225 printf("*** Unsupported type: %.3s\n", failed_type);
1226#endif
1227 return false;
1228 }
1229 break;
1230 case 'T':
Jason Molenda026aa492014-10-15 22:11:15 +00001231 ++m_read_ptr;
1232 if (!ParseTemplateParam())
1233 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001234 break;
1235 case 'M':
Jason Molenda026aa492014-10-15 22:11:15 +00001236 ++m_read_ptr;
1237 if (!ParsePointerToMemberType())
1238 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001239 break;
1240 case 'A':
Jason Molenda026aa492014-10-15 22:11:15 +00001241 ++m_read_ptr;
1242 if (!ParseArrayType())
1243 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001244 break;
1245 case 'F':
Jason Molenda026aa492014-10-15 22:11:15 +00001246 ++m_read_ptr;
1247 if (!ParseFunctionType())
1248 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001249 break;
1250 case 'S':
Jason Molenda026aa492014-10-15 22:11:15 +00001251 if (*++m_read_ptr == 't')
Kate Stonee2b21862014-07-22 17:03:38 +00001252 {
Jason Molenda026aa492014-10-15 22:11:15 +00001253 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001254 WriteStdPrefix();
Jason Molenda026aa492014-10-15 22:11:15 +00001255 if (!ParseName())
1256 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001257 }
1258 else
1259 {
1260 suppress_substitution = true;
Jason Molenda026aa492014-10-15 22:11:15 +00001261 if (!ParseSubstitution())
1262 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001263 }
1264 break;
1265 case 'P':
1266 {
Jason Molenda026aa492014-10-15 22:11:15 +00001267 switch (*++m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00001268 {
1269 case 'F':
Jason Molenda026aa492014-10-15 22:11:15 +00001270 ++m_read_ptr;
1271 if (!ParseFunctionType(QualifierPointer))
1272 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001273 break;
1274 default:
Jason Molenda026aa492014-10-15 22:11:15 +00001275 if (!ParseType())
1276 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001277 Write('*');
1278 break;
1279 }
1280 break;
1281 }
1282 case 'R':
1283 {
Jason Molenda026aa492014-10-15 22:11:15 +00001284 ++m_read_ptr;
1285 if (!ParseType())
1286 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001287 Write('&');
1288 break;
1289 }
1290 case 'O':
1291 {
Jason Molenda026aa492014-10-15 22:11:15 +00001292 ++m_read_ptr;
1293 if (!ParseType())
1294 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001295 Write('&');
1296 Write('&');
1297 break;
1298 }
1299 case 'C':
1300 case 'G':
1301 case 'U':
1302#ifdef DEBUG_FAILURES
1303 printf("*** Unsupported type: %.3s\n", failed_type);
1304#endif
1305 return false;
1306 // Test for common cases to avoid TryParseBuiltinType() overhead
1307 case 'N':
1308 case 'Z':
1309 case 'L':
Jason Molenda026aa492014-10-15 22:11:15 +00001310 if (!ParseName())
1311 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001312 break;
1313 default:
Jason Molenda026aa492014-10-15 22:11:15 +00001314 if (const char *builtin = TryParseBuiltinType())
Kate Stonee2b21862014-07-22 17:03:38 +00001315 {
1316 Write(builtin);
1317 suppress_substitution = true;
1318 }
1319 else
1320 {
Jason Molenda026aa492014-10-15 22:11:15 +00001321 if (!ParseName())
1322 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001323 }
1324 break;
1325 }
Jason Molenda026aa492014-10-15 22:11:15 +00001326
Kate Stonee2b21862014-07-22 17:03:38 +00001327 // Allow base substitutions to be suppressed, but always record
1328 // substitutions for the qualified variant
Jason Molenda026aa492014-10-15 22:11:15 +00001329 if (!suppress_substitution)
1330 EndSubstitution(type_start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001331 if (qualifiers)
1332 {
1333 WriteQualifiers(qualifiers, false);
1334 EndSubstitution(type_start_cookie);
1335 }
1336 return true;
1337 }
Jason Molenda026aa492014-10-15 22:11:15 +00001338
Kate Stonee2b21862014-07-22 17:03:38 +00001339 // <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
1340 // ::= <closure-type-name>
1341 //
1342 // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
1343 //
1344 // <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Jason Molenda026aa492014-10-15 22:11:15 +00001345
1346 bool
1347 ParseUnnamedTypeName(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001348 {
Jason Molenda026aa492014-10-15 22:11:15 +00001349 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001350 {
1351 case 't':
1352 {
1353 int cookie = GetStartCookie();
1354 WRITE("'unnamed");
Jason Molenda026aa492014-10-15 22:11:15 +00001355 const char *before_digits = m_read_ptr;
1356 if (TryParseNumber() != -1) Write (before_digits,
1357 m_read_ptr - before_digits);
1358 if (!Parse('_'))
1359 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001360 Write('\'');
Jason Molenda026aa492014-10-15 22:11:15 +00001361 name_state.last_name_range = EndRange (cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001362 return true;
1363 }
1364 case 'b':
1365 {
1366 int cookie = GetStartCookie();
1367 WRITE("'block");
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 'l':
1378#ifdef DEBUG_FAILURES
1379 printf("*** Lambda type names unsupported\n");
1380#endif
1381 return false;
1382 }
1383#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001384 printf("*** Unknown unnamed type %.3s\n", m_read_ptr - 2);
Kate Stonee2b21862014-07-22 17:03:38 +00001385#endif
1386 return false;
1387 }
Jason Molenda026aa492014-10-15 22:11:15 +00001388
Kate Stonee2b21862014-07-22 17:03:38 +00001389 // <ctor-dtor-name> ::= C1 # complete object constructor
1390 // ::= C2 # base object constructor
1391 // ::= C3 # complete object allocating constructor
Jason Molenda026aa492014-10-15 22:11:15 +00001392
1393 bool
1394 ParseCtor(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001395 {
Jason Molenda026aa492014-10-15 22:11:15 +00001396 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001397 if (next == '1' || next == '2' || next == '3' || next == '5')
1398 {
Jason Molenda026aa492014-10-15 22:11:15 +00001399 RewriteRange (name_state.last_name_range);
Kate Stonee2b21862014-07-22 17:03:38 +00001400 name_state.has_no_return_type = true;
Jason Molenda026aa492014-10-15 22:11:15 +00001401 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001402 return true;
1403 }
1404#ifdef DEBUG_FAILURES
1405 printf("*** Broken constructor\n");
1406#endif
1407 return false;
1408 }
Jason Molenda026aa492014-10-15 22:11:15 +00001409
Kate Stonee2b21862014-07-22 17:03:38 +00001410 // <ctor-dtor-name> ::= D0 # deleting destructor
1411 // ::= D1 # complete object destructor
1412 // ::= D2 # base object destructor
Jason Molenda026aa492014-10-15 22:11:15 +00001413
1414 bool
1415 ParseDtor(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001416 {
Jason Molenda026aa492014-10-15 22:11:15 +00001417 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001418 if (next == '0' || next == '1' || next == '2' || next == '5')
1419 {
1420 Write('~');
1421 RewriteRange(name_state.last_name_range);
1422 name_state.has_no_return_type = true;
Jason Molenda026aa492014-10-15 22:11:15 +00001423 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001424 return true;
1425 }
1426#ifdef DEBUG_FAILURES
1427 printf("*** Broken destructor\n");
1428#endif
1429 return false;
1430 }
Jason Molenda026aa492014-10-15 22:11:15 +00001431
Kate Stonee2b21862014-07-22 17:03:38 +00001432 // See TryParseOperator()
Jason Molenda026aa492014-10-15 22:11:15 +00001433
1434 bool
1435 ParseOperatorName(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001436 {
1437#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001438 const char *operator_ptr = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001439#endif
1440 Operator parsed_operator = TryParseOperator();
1441 if (parsed_operator.name)
1442 {
1443 WRITE("operator");
1444 Write(parsed_operator.name);
1445 return true;
1446 }
Jason Molenda026aa492014-10-15 22:11:15 +00001447
Kate Stonee2b21862014-07-22 17:03:38 +00001448 // Handle special operators
1449 switch (parsed_operator.kind)
1450 {
1451 case OperatorKind::Vendor:
1452 WRITE("operator ");
1453 return ParseSourceName();
1454 case OperatorKind::ConversionOperator:
1455 ResetTemplateArgs();
1456 name_state.has_no_return_type = true;
1457 WRITE("operator ");
1458 return ParseType();
1459 default:
1460#ifdef DEBUG_FAILURES
1461 printf("*** Unknown operator: %.2s\n", operator_ptr);
1462#endif
1463 return false;
1464 }
1465 }
Jason Molenda026aa492014-10-15 22:11:15 +00001466
Kate Stonee2b21862014-07-22 17:03:38 +00001467 // <source-name> ::= <positive length number> <identifier>
Jason Molenda026aa492014-10-15 22:11:15 +00001468
1469 bool
1470 ParseSourceName()
Kate Stonee2b21862014-07-22 17:03:38 +00001471 {
1472 int count = TryParseNumber();
1473 if (count == -1)
1474 {
1475#ifdef DEBUG_FAILURES
1476 printf("*** Malformed source name, missing length count\n");
1477#endif
1478 return false;
1479 }
Jason Molenda026aa492014-10-15 22:11:15 +00001480
1481 const char *next_m_read_ptr = m_read_ptr + count;
1482 if (next_m_read_ptr > m_read_end)
Kate Stonee2b21862014-07-22 17:03:38 +00001483 {
1484#ifdef DEBUG_FAILURES
1485 printf("*** Malformed source name, premature termination\n");
1486#endif
1487 return false;
1488 }
Jason Molenda026aa492014-10-15 22:11:15 +00001489
1490 if (count >= 10 && strncmp(m_read_ptr, "_GLOBAL__N", 10) == 0)
1491 WRITE("(anonymous namespace)");
1492 else Write(m_read_ptr, count);
1493
1494 m_read_ptr = next_m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001495 return true;
1496 }
Jason Molenda026aa492014-10-15 22:11:15 +00001497
Kate Stonee2b21862014-07-22 17:03:38 +00001498 // <unqualified-name> ::= <operator-name>
1499 // ::= <ctor-dtor-name>
1500 // ::= <source-name>
1501 // ::= <unnamed-type-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001502
1503 bool
1504 ParseUnqualifiedName(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001505 {
1506 // Note that these are detected directly in ParseNestedName for
1507 // performance rather than switching on the same options twice
Jason Molenda026aa492014-10-15 22:11:15 +00001508 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001509 switch (next)
1510 {
1511 case 'C':
Jason Molenda026aa492014-10-15 22:11:15 +00001512 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001513 return ParseCtor(name_state);
1514 case 'D':
Jason Molenda026aa492014-10-15 22:11:15 +00001515 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001516 return ParseDtor(name_state);
1517 case 'U':
Jason Molenda026aa492014-10-15 22:11:15 +00001518 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001519 return ParseUnnamedTypeName(name_state);
1520 case '0':
1521 case '1':
1522 case '2':
1523 case '3':
1524 case '4':
1525 case '5':
1526 case '6':
1527 case '7':
1528 case '8':
1529 case '9':
1530 {
1531 int name_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001532 if (!ParseSourceName())
1533 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001534 name_state.last_name_range = EndRange(name_start_cookie);
1535 return true;
1536 }
1537 default:
1538 return ParseOperatorName(name_state);
1539 };
1540 }
Jason Molenda026aa492014-10-15 22:11:15 +00001541
Kate Stonee2b21862014-07-22 17:03:38 +00001542 // <unscoped-name> ::= <unqualified-name>
1543 // ::= St <unqualified-name> # ::std::
1544 // extension ::= StL<unqualified-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001545
1546 bool
1547 ParseUnscopedName(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001548 {
Jason Molenda026aa492014-10-15 22:11:15 +00001549 if (*m_read_ptr == 'S' && *(m_read_ptr + 1) == 't')
Kate Stonee2b21862014-07-22 17:03:38 +00001550 {
1551 WriteStdPrefix();
Jason Molenda026aa492014-10-15 22:11:15 +00001552 if (*(m_read_ptr += 2) == 'L')
1553 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001554 }
1555 return ParseUnqualifiedName(name_state);
1556 }
Jason Molenda026aa492014-10-15 22:11:15 +00001557
1558 bool
1559 ParseIntegerLiteral(const char *prefix, const char *suffix,
Kate Stonee2b21862014-07-22 17:03:38 +00001560 bool allow_negative)
1561 {
Jason Molenda026aa492014-10-15 22:11:15 +00001562 if (prefix)
1563 Write(prefix);
1564 if (!ParseNumber(allow_negative))
1565 return false;
1566 if (suffix)
1567 Write(suffix);
Kate Stonee2b21862014-07-22 17:03:38 +00001568 return Parse('E');
1569 }
Jason Molenda026aa492014-10-15 22:11:15 +00001570
1571 bool
1572 ParseBooleanLiteral()
Kate Stonee2b21862014-07-22 17:03:38 +00001573 {
Jason Molenda026aa492014-10-15 22:11:15 +00001574 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001575 {
1576 case '0': WRITE("false"); break;
1577 case '1': WRITE("true"); break;
1578 default:
1579#ifdef DEBUG_FAILURES
1580 printf("*** Boolean literal not 0 or 1\n");
1581#endif
1582 return false;
1583 }
1584 return Parse('E');
1585 }
Jason Molenda026aa492014-10-15 22:11:15 +00001586
Kate Stonee2b21862014-07-22 17:03:38 +00001587 // <expr-primary> ::= L <type> <value number> E # integer literal
1588 // ::= L <type> <value float> E # floating literal
1589 // ::= L <string type> E # string literal
1590 // ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
1591 // ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
1592 // ::= L <mangled-name> E # external name
Jason Molenda026aa492014-10-15 22:11:15 +00001593
1594 bool
1595 ParseExpressionPrimary()
Kate Stonee2b21862014-07-22 17:03:38 +00001596 {
Jason Molenda026aa492014-10-15 22:11:15 +00001597 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001598 {
1599 case 'b': return ParseBooleanLiteral();
1600 case 'x': return ParseIntegerLiteral(nullptr, "ll", true);
1601 case 'l': return ParseIntegerLiteral(nullptr, "l", true);
1602 case 'i': return ParseIntegerLiteral(nullptr, nullptr, true);
1603 case 'n': return ParseIntegerLiteral("(__int128)", nullptr, true);
1604 case 'j': return ParseIntegerLiteral(nullptr, "u", false);
1605 case 'm': return ParseIntegerLiteral(nullptr, "ul", false);
1606 case 'y': return ParseIntegerLiteral(nullptr, "ull", false);
1607 case 'o': return ParseIntegerLiteral("(unsigned __int128)",
1608 nullptr, false);
1609 case '_':
Jason Molenda026aa492014-10-15 22:11:15 +00001610 if (*m_read_ptr++ == 'Z')
Kate Stonee2b21862014-07-22 17:03:38 +00001611 {
Jason Molenda026aa492014-10-15 22:11:15 +00001612 if (!ParseEncoding())
1613 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001614 return Parse('E');
1615 }
Jason Molenda026aa492014-10-15 22:11:15 +00001616 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001617 // fallthrough
1618 case 'w':
1619 case 'c':
1620 case 'a':
1621 case 'h':
1622 case 's':
1623 case 't':
1624 case 'f':
1625 case 'd':
1626 case 'e':
1627#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001628 printf("*** Unsupported primary expression %.5s\n", m_read_ptr - 1);
Kate Stonee2b21862014-07-22 17:03:38 +00001629#endif
1630 return false;
1631 case 'T':
1632 // Invalid mangled name per
1633 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
1634#ifdef DEBUG_FAILURES
1635 printf("*** Invalid primary expr encoding\n");
1636#endif
1637 return false;
1638 default:
Jason Molenda026aa492014-10-15 22:11:15 +00001639 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001640 Write('(');
Jason Molenda026aa492014-10-15 22:11:15 +00001641 if (!ParseType())
1642 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001643 Write(')');
Jason Molenda026aa492014-10-15 22:11:15 +00001644 if (!ParseNumber())
1645 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001646 return Parse('E');
1647 }
1648 }
Jason Molenda026aa492014-10-15 22:11:15 +00001649
Kate Stonee2b21862014-07-22 17:03:38 +00001650 // <unresolved-type> ::= <template-param>
1651 // ::= <decltype>
1652 // ::= <substitution>
Jason Molenda026aa492014-10-15 22:11:15 +00001653
1654 bool
1655 ParseUnresolvedType()
Kate Stonee2b21862014-07-22 17:03:38 +00001656 {
1657 int type_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001658 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001659 {
1660 case 'T':
Jason Molenda026aa492014-10-15 22:11:15 +00001661 if (!ParseTemplateParam())
1662 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001663 EndSubstitution(type_start_cookie);
1664 return true;
1665 case 'S':
1666 {
Jason Molenda026aa492014-10-15 22:11:15 +00001667 if (*m_read_ptr != 't')
1668 return ParseSubstitution();
1669
1670 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001671 WriteStdPrefix();
1672 NameState type_name = {};
Jason Molenda026aa492014-10-15 22:11:15 +00001673 if (!ParseUnqualifiedName(type_name))
1674 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001675 EndSubstitution(type_start_cookie);
1676 return true;
Jason Molenda026aa492014-10-15 22:11:15 +00001677
Kate Stonee2b21862014-07-22 17:03:38 +00001678 }
1679 case 'D':
1680 default:
1681#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001682 printf("*** Unsupported unqualified type: %3s\n", m_read_ptr - 1);
Kate Stonee2b21862014-07-22 17:03:38 +00001683#endif
1684 return false;
1685 }
1686 }
Jason Molenda026aa492014-10-15 22:11:15 +00001687
Kate Stonee2b21862014-07-22 17:03:38 +00001688 // <base-unresolved-name> ::= <simple-id> # unresolved name
1689 // extension ::= <operator-name> # unresolved operator-function-id
1690 // extension ::= <operator-name> <template-args> # unresolved operator template-id
1691 // ::= on <operator-name> # unresolved operator-function-id
1692 // ::= on <operator-name> <template-args> # unresolved operator template-id
1693 // ::= dn <destructor-name> # destructor or pseudo-destructor;
1694 // # e.g. ~X or ~X<N-1>
Jason Molenda026aa492014-10-15 22:11:15 +00001695
1696 bool
1697 ParseBaseUnresolvedName()
Kate Stonee2b21862014-07-22 17:03:38 +00001698 {
1699#ifdef DEBUG_FAILURES
1700 printf("*** Base unresolved name unsupported\n");
1701#endif
1702 return false;
1703 }
Jason Molenda026aa492014-10-15 22:11:15 +00001704
Kate Stonee2b21862014-07-22 17:03:38 +00001705 // <unresolved-name>
1706 // extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
1707 // ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
1708 // ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
1709 // # A::x, N::y, A<T>::z; "gs" means leading "::"
1710 // ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
1711 // extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
1712 // # T::N::x /decltype(p)::N::x
1713 // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001714
1715 bool
1716 ParseUnresolvedName()
Kate Stonee2b21862014-07-22 17:03:38 +00001717 {
1718#ifdef DEBUG_FAILURES
1719 printf("*** Unresolved names not supported\n");
1720#endif
1721 //TODO: grammar for all of this seems unclear...
1722 return false;
Jason Molenda026aa492014-10-15 22:11:15 +00001723
1724 if (*m_read_ptr == 'g' && *(m_read_ptr + 1) == 's')
Kate Stonee2b21862014-07-22 17:03:38 +00001725 {
Jason Molenda026aa492014-10-15 22:11:15 +00001726 m_read_ptr += 2;
Kate Stonee2b21862014-07-22 17:03:38 +00001727 WriteNamespaceSeparator();
1728 }
1729 }
Jason Molenda026aa492014-10-15 22:11:15 +00001730
Kate Stonee2b21862014-07-22 17:03:38 +00001731 // <expression> ::= <unary operator-name> <expression>
1732 // ::= <binary operator-name> <expression> <expression>
1733 // ::= <ternary operator-name> <expression> <expression> <expression>
1734 // ::= cl <expression>+ E # call
1735 // ::= cv <type> <expression> # conversion with one argument
1736 // ::= cv <type> _ <expression>* E # conversion with a different number of arguments
1737 // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
1738 // ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
1739 // ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
1740 // ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1741 // ::= [gs] dl <expression> # delete expression
1742 // ::= [gs] da <expression> # delete[] expression
1743 // ::= pp_ <expression> # prefix ++
1744 // ::= mm_ <expression> # prefix --
1745 // ::= ti <type> # typeid (type)
1746 // ::= te <expression> # typeid (expression)
1747 // ::= dc <type> <expression> # dynamic_cast<type> (expression)
1748 // ::= sc <type> <expression> # static_cast<type> (expression)
1749 // ::= cc <type> <expression> # const_cast<type> (expression)
1750 // ::= rc <type> <expression> # reinterpret_cast<type> (expression)
1751 // ::= st <type> # sizeof (a type)
1752 // ::= sz <expression> # sizeof (an expression)
1753 // ::= at <type> # alignof (a type)
1754 // ::= az <expression> # alignof (an expression)
1755 // ::= nx <expression> # noexcept (expression)
1756 // ::= <template-param>
1757 // ::= <function-param>
1758 // ::= dt <expression> <unresolved-name> # expr.name
1759 // ::= pt <expression> <unresolved-name> # expr->name
1760 // ::= ds <expression> <expression> # expr.*expr
1761 // ::= sZ <template-param> # size of a parameter pack
1762 // ::= sZ <function-param> # size of a function parameter pack
1763 // ::= sp <expression> # pack expansion
1764 // ::= tw <expression> # throw expression
1765 // ::= tr # throw with no operand (rethrow)
1766 // ::= <unresolved-name> # f(p), N::f(p), ::f(p),
1767 // # freestanding dependent name (e.g., T::x),
1768 // # objectless nonstatic member reference
1769 // ::= <expr-primary>
Jason Molenda026aa492014-10-15 22:11:15 +00001770
1771 bool
1772 ParseExpression()
Kate Stonee2b21862014-07-22 17:03:38 +00001773 {
1774 Operator expression_operator = TryParseOperator();
1775 switch (expression_operator.kind)
1776 {
1777 case OperatorKind::Unary:
1778 Write(expression_operator.name);
1779 Write('(');
Jason Molenda026aa492014-10-15 22:11:15 +00001780 if (!ParseExpression())
1781 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001782 Write(')');
1783 return true;
1784 case OperatorKind::Binary:
Jason Molenda026aa492014-10-15 22:11:15 +00001785 if (!ParseExpression())
1786 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001787 Write(expression_operator.name);
1788 return ParseExpression();
1789 case OperatorKind::Ternary:
Jason Molenda026aa492014-10-15 22:11:15 +00001790 if (!ParseExpression())
1791 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001792 Write('?');
Jason Molenda026aa492014-10-15 22:11:15 +00001793 if (!ParseExpression())
1794 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001795 Write(':');
1796 return ParseExpression();
1797 case OperatorKind::NoMatch:
1798 break;
1799 case OperatorKind::Other:
1800 default:
1801#ifdef DEBUG_FAILURES
1802 printf("*** Unsupported operator: %s\n", expression_operator.name);
1803#endif
1804 return false;
1805 }
Jason Molenda026aa492014-10-15 22:11:15 +00001806
1807 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001808 {
1809 case 'T': return ParseTemplateParam();
1810 case 'L': return ParseExpressionPrimary();
1811 case 's':
Jason Molenda026aa492014-10-15 22:11:15 +00001812 if (*m_read_ptr++ == 'r')
1813 return ParseUnresolvedName();
1814 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001815 // fallthrough
1816 default:
1817 return ParseExpressionPrimary();
1818 }
1819 }
Jason Molenda026aa492014-10-15 22:11:15 +00001820
Kate Stonee2b21862014-07-22 17:03:38 +00001821 // <template-arg> ::= <type> # type or template
1822 // ::= X <expression> E # expression
1823 // ::= <expr-primary> # simple expressions
1824 // ::= J <template-arg>* E # argument pack
1825 // ::= LZ <encoding> E # extension
Jason Molenda026aa492014-10-15 22:11:15 +00001826
1827 bool
1828 ParseTemplateArg()
Kate Stonee2b21862014-07-22 17:03:38 +00001829 {
Jason Molenda026aa492014-10-15 22:11:15 +00001830 switch (*m_read_ptr) {
Kate Stonee2b21862014-07-22 17:03:38 +00001831 case 'J':
1832#ifdef DEBUG_FAILURES
1833 printf("*** Template argument packs unsupported\n");
1834#endif
1835 return false;
1836 case 'X':
Jason Molenda026aa492014-10-15 22:11:15 +00001837 ++m_read_ptr;
1838 if (!ParseExpression())
1839 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001840 return Parse('E');
1841 case 'L':
Jason Molenda026aa492014-10-15 22:11:15 +00001842 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001843 return ParseExpressionPrimary();
1844 default:
1845 return ParseType();
1846 }
1847 }
Jason Molenda026aa492014-10-15 22:11:15 +00001848
Kate Stonee2b21862014-07-22 17:03:38 +00001849 // <template-args> ::= I <template-arg>* E
1850 // extension, the abi says <template-arg>+
Jason Molenda026aa492014-10-15 22:11:15 +00001851
1852 bool
1853 ParseTemplateArgs(bool record_template_args = false)
Kate Stonee2b21862014-07-22 17:03:38 +00001854 {
Jason Molenda026aa492014-10-15 22:11:15 +00001855 if (record_template_args)
1856 ResetTemplateArgs();
1857
Kate Stonee2b21862014-07-22 17:03:38 +00001858 bool first_arg = true;
Jason Molenda026aa492014-10-15 22:11:15 +00001859 while (*m_read_ptr != 'E')
Kate Stonee2b21862014-07-22 17:03:38 +00001860 {
Jason Molenda026aa492014-10-15 22:11:15 +00001861 if (first_arg)
1862 first_arg = false;
Kate Stonee2b21862014-07-22 17:03:38 +00001863 else WriteCommaSpace();
Jason Molenda026aa492014-10-15 22:11:15 +00001864
Kate Stonee2b21862014-07-22 17:03:38 +00001865 int template_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001866 if (!ParseTemplateArg())
1867 return false;
1868 if (record_template_args)
1869 EndTemplateArg(template_start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001870 }
Jason Molenda026aa492014-10-15 22:11:15 +00001871 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001872 return true;
1873 }
Jason Molenda026aa492014-10-15 22:11:15 +00001874
Kate Stonee2b21862014-07-22 17:03:38 +00001875 // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
1876 // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
1877 //
1878 // <prefix> ::= <prefix> <unqualified-name>
1879 // ::= <template-prefix> <template-args>
1880 // ::= <template-param>
1881 // ::= <decltype>
1882 // ::= # empty
1883 // ::= <substitution>
1884 // ::= <prefix> <data-member-prefix>
1885 // extension ::= L
1886 //
1887 // <template-prefix> ::= <prefix> <template unqualified-name>
1888 // ::= <template-param>
1889 // ::= <substitution>
1890 //
1891 // <unqualified-name> ::= <operator-name>
1892 // ::= <ctor-dtor-name>
1893 // ::= <source-name>
1894 // ::= <unnamed-type-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001895
1896 bool
1897 ParseNestedName(NameState & name_state, bool parse_discriminator = false)
Kate Stonee2b21862014-07-22 17:03:38 +00001898 {
1899 int qualifiers = TryParseQualifiers(true, true);
1900 bool first_part = true;
1901 bool suppress_substitution = true;
1902 int name_start_cookie = GetStartCookie();
1903 while (true)
1904 {
Jason Molenda026aa492014-10-15 22:11:15 +00001905 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001906 if (next == 'E')
1907 {
Jason Molenda026aa492014-10-15 22:11:15 +00001908 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001909 break;
1910 }
Jason Molenda026aa492014-10-15 22:11:15 +00001911
Kate Stonee2b21862014-07-22 17:03:38 +00001912 // Record a substitution candidate for all prefixes, but not the full name
Jason Molenda026aa492014-10-15 22:11:15 +00001913 if (suppress_substitution)
1914 suppress_substitution = false;
Kate Stonee2b21862014-07-22 17:03:38 +00001915 else EndSubstitution(name_start_cookie);
Jason Molenda026aa492014-10-15 22:11:15 +00001916
Kate Stonee2b21862014-07-22 17:03:38 +00001917 if (next == 'I')
1918 {
Jason Molenda026aa492014-10-15 22:11:15 +00001919 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001920 name_state.is_last_generic = true;
1921 WriteTemplateStart();
Jason Molenda026aa492014-10-15 22:11:15 +00001922 if (!ParseTemplateArgs(name_state.parse_function_params))
1923 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001924 WriteTemplateEnd();
1925 continue;
1926 }
Jason Molenda026aa492014-10-15 22:11:15 +00001927
1928 if (first_part)
1929 first_part = false;
Kate Stonee2b21862014-07-22 17:03:38 +00001930 else WriteNamespaceSeparator();
Jason Molenda026aa492014-10-15 22:11:15 +00001931
Kate Stonee2b21862014-07-22 17:03:38 +00001932 name_state.is_last_generic = false;
1933 switch (next)
1934 {
1935 case '0':
1936 case '1':
1937 case '2':
1938 case '3':
1939 case '4':
1940 case '5':
1941 case '6':
1942 case '7':
1943 case '8':
1944 case '9':
1945 {
1946 int name_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001947 if (!ParseSourceName())
1948 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001949 name_state.last_name_range = EndRange(name_start_cookie);
1950 continue;
1951 }
1952 case 'S':
Jason Molenda026aa492014-10-15 22:11:15 +00001953 if (*++m_read_ptr == 't')
Kate Stonee2b21862014-07-22 17:03:38 +00001954 {
1955 WriteStdPrefix();
Jason Molenda026aa492014-10-15 22:11:15 +00001956 ++m_read_ptr;
1957 if (!ParseUnqualifiedName(name_state))
1958 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001959 }
1960 else
1961 {
Jason Molenda026aa492014-10-15 22:11:15 +00001962 if (!ParseSubstitution())
1963 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001964 suppress_substitution = true;
1965 }
1966 continue;
1967 case 'T':
Jason Molenda026aa492014-10-15 22:11:15 +00001968 ++m_read_ptr;
1969 if (!ParseTemplateParam())
1970 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001971 continue;
1972 case 'C':
Jason Molenda026aa492014-10-15 22:11:15 +00001973 ++m_read_ptr;
1974 if (!ParseCtor(name_state))
1975 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001976 continue;
1977 case 'D':
1978 {
Jason Molenda026aa492014-10-15 22:11:15 +00001979 switch (*(m_read_ptr + 1))
Kate Stonee2b21862014-07-22 17:03:38 +00001980 {
1981 case 't':
1982 case 'T':
1983#ifdef DEBUG_FAILURES
1984 printf("*** Decltype unsupported\n");
1985#endif
1986 return false;
1987 }
Jason Molenda026aa492014-10-15 22:11:15 +00001988 ++m_read_ptr;
1989 if (!ParseDtor(name_state))
1990 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001991 continue;
1992 }
1993 case 'U':
Jason Molenda026aa492014-10-15 22:11:15 +00001994 ++m_read_ptr;
1995 if (!ParseUnnamedTypeName(name_state))
1996 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001997 continue;
1998 case 'L':
Jason Molenda026aa492014-10-15 22:11:15 +00001999 ++m_read_ptr;
2000 if (!ParseUnqualifiedName(name_state))
2001 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002002 continue;
2003 default:
Jason Molenda026aa492014-10-15 22:11:15 +00002004 if (!ParseOperatorName(name_state))
2005 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002006 }
2007 }
Jason Molenda026aa492014-10-15 22:11:15 +00002008
2009 if (parse_discriminator)
2010 TryParseDiscriminator();
2011 if (name_state.parse_function_params
2012 && !ParseFunctionArgs(name_state, name_start_cookie))
2013 {
2014 return false;
2015 }
2016 if (qualifiers)
2017 WriteQualifiers(qualifiers);
Kate Stonee2b21862014-07-22 17:03:38 +00002018 return true;
2019 }
Jason Molenda026aa492014-10-15 22:11:15 +00002020
Kate Stonee2b21862014-07-22 17:03:38 +00002021 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2022 // := Z <function encoding> E s [<discriminator>]
2023 // := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Jason Molenda026aa492014-10-15 22:11:15 +00002024
2025 bool
2026 ParseLocalName(bool parse_function_params)
Kate Stonee2b21862014-07-22 17:03:38 +00002027 {
Jason Molenda026aa492014-10-15 22:11:15 +00002028 if (!ParseEncoding())
2029 return false;
2030 if (!Parse('E'))
2031 return false;
2032
2033 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002034 {
2035 case 's':
2036 TryParseDiscriminator(); // Optional and ignored
2037 WRITE("::string literal");
2038 break;
2039 case 'd':
2040 TryParseNumber(); // Optional and ignored
2041 WriteNamespaceSeparator();
Jason Molenda026aa492014-10-15 22:11:15 +00002042 if (!ParseName())
2043 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002044 break;
2045 default:
2046 WriteNamespaceSeparator();
Jason Molenda026aa492014-10-15 22:11:15 +00002047 if (!ParseName(parse_function_params, true))
2048 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002049 TryParseDiscriminator(); // Optional and ignored
2050 }
2051 return true;
2052 }
Jason Molenda026aa492014-10-15 22:11:15 +00002053
Kate Stonee2b21862014-07-22 17:03:38 +00002054 // <name> ::= <nested-name>
2055 // ::= <local-name>
2056 // ::= <unscoped-template-name> <template-args>
2057 // ::= <unscoped-name>
Jason Molenda026aa492014-10-15 22:11:15 +00002058
Kate Stonee2b21862014-07-22 17:03:38 +00002059 // <unscoped-template-name> ::= <unscoped-name>
2060 // ::= <substitution>
Jason Molenda026aa492014-10-15 22:11:15 +00002061
2062 bool
2063 ParseName(bool parse_function_params = false,
Kate Stonee2b21862014-07-22 17:03:38 +00002064 bool parse_discriminator = false)
2065 {
2066 NameState name_state = { parse_function_params };
2067 int name_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00002068
2069 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002070 {
2071 case 'N':
Jason Molenda026aa492014-10-15 22:11:15 +00002072 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002073 return ParseNestedName(name_state, parse_discriminator);
2074 case 'Z':
2075 {
Jason Molenda026aa492014-10-15 22:11:15 +00002076 ++m_read_ptr;
2077 if (!ParseLocalName(parse_function_params))
2078 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002079 break;
2080 }
2081 case 'L':
Jason Molenda026aa492014-10-15 22:11:15 +00002082 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002083 // fallthrough
2084 default:
2085 {
Jason Molenda026aa492014-10-15 22:11:15 +00002086 if (!ParseUnscopedName(name_state))
2087 return false;
2088
2089 if (*m_read_ptr == 'I')
Kate Stonee2b21862014-07-22 17:03:38 +00002090 {
2091 EndSubstitution(name_start_cookie);
Jason Molenda026aa492014-10-15 22:11:15 +00002092
2093 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002094 name_state.is_last_generic = true;
2095 WriteTemplateStart();
Jason Molenda026aa492014-10-15 22:11:15 +00002096 if (!ParseTemplateArgs(parse_function_params))
2097 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002098 WriteTemplateEnd();
2099 }
2100 break;
2101 }
2102 }
Jason Molenda026aa492014-10-15 22:11:15 +00002103 if (parse_discriminator)
2104 TryParseDiscriminator();
Kate Stonee2b21862014-07-22 17:03:38 +00002105 if (parse_function_params &&
Jason Molenda026aa492014-10-15 22:11:15 +00002106 !ParseFunctionArgs(name_state, name_start_cookie))
2107 {
2108 return false;
2109 }
Kate Stonee2b21862014-07-22 17:03:38 +00002110 return true;
2111 }
Jason Molenda026aa492014-10-15 22:11:15 +00002112
Kate Stonee2b21862014-07-22 17:03:38 +00002113 // <call-offset> ::= h <nv-offset> _
2114 // ::= v <v-offset> _
2115 //
2116 // <nv-offset> ::= <offset number>
2117 // # non-virtual base override
2118 //
2119 // <v-offset> ::= <offset number> _ <virtual offset number>
2120 // # virtual base override, with vcall offset
Jason Molenda026aa492014-10-15 22:11:15 +00002121
2122 bool
2123 ParseCallOffset()
Kate Stonee2b21862014-07-22 17:03:38 +00002124 {
Jason Molenda026aa492014-10-15 22:11:15 +00002125 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00002126 {
2127 case 'h':
Jason Molenda026aa492014-10-15 22:11:15 +00002128 if (*m_read_ptr == 'n')
2129 ++m_read_ptr;
2130 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2131 break;
Kate Stonee2b21862014-07-22 17:03:38 +00002132 return true;
2133 case 'v':
Jason Molenda026aa492014-10-15 22:11:15 +00002134 if (*m_read_ptr == 'n')
2135 ++m_read_ptr;
2136 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2137 break;
2138 if (*m_read_ptr == 'n')
2139 ++m_read_ptr;
2140 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2141 break;
Kate Stonee2b21862014-07-22 17:03:38 +00002142 return true;
2143 }
2144#ifdef DEBUG_FAILURES
2145 printf("*** Malformed call offset\n");
2146#endif
2147 return false;
2148 }
Jason Molenda026aa492014-10-15 22:11:15 +00002149
Kate Stonee2b21862014-07-22 17:03:38 +00002150 // <special-name> ::= TV <type> # virtual table
2151 // ::= TT <type> # VTT structure (construction vtable index)
2152 // ::= TI <type> # typeinfo structure
2153 // ::= TS <type> # typeinfo name (null-terminated byte string)
2154 // ::= Tc <call-offset> <call-offset> <base encoding>
2155 // # base is the nominal target function of thunk
2156 // # first call-offset is 'this' adjustment
2157 // # second call-offset is result adjustment
2158 // ::= T <call-offset> <base encoding>
2159 // # base is the nominal target function of thunk
2160 // extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
Jason Molenda026aa492014-10-15 22:11:15 +00002161
2162 bool
2163 ParseSpecialNameT()
Kate Stonee2b21862014-07-22 17:03:38 +00002164 {
Jason Molenda026aa492014-10-15 22:11:15 +00002165 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00002166 {
2167 case 'V':
2168 WRITE("vtable for ");
2169 return ParseType();
2170 case 'T':
2171 WRITE("VTT for ");
2172 return ParseType();
2173 case 'I':
2174 WRITE("typeinfo for ");
2175 return ParseType();
2176 case 'S':
2177 WRITE("typeinfo name for ");
2178 return ParseType();
2179 case 'c':
2180 case 'C':
2181#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00002182 printf("*** Unsupported thunk or construction vtable name: %.3s\n", m_read_ptr - 1);
Kate Stonee2b21862014-07-22 17:03:38 +00002183#endif
2184 return false;
2185 default:
Jason Molenda026aa492014-10-15 22:11:15 +00002186 if (*--m_read_ptr == 'v')
Kate Stonee2b21862014-07-22 17:03:38 +00002187 {
2188 WRITE("virtual thunk to ");
2189 }
2190 else
2191 {
2192 WRITE("non-virtual thunk to ");
2193 }
Jason Molenda026aa492014-10-15 22:11:15 +00002194 if (!ParseCallOffset())
2195 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002196 return ParseEncoding();
2197 }
2198 }
Jason Molenda026aa492014-10-15 22:11:15 +00002199
Kate Stonee2b21862014-07-22 17:03:38 +00002200 // <special-name> ::= GV <object name> # Guard variable for one-time initialization
2201 // # No <type>
2202 // extension ::= GR <object name> # reference temporary for object
Jason Molenda026aa492014-10-15 22:11:15 +00002203
2204 bool
2205 ParseSpecialNameG()
Kate Stonee2b21862014-07-22 17:03:38 +00002206 {
Jason Molenda026aa492014-10-15 22:11:15 +00002207 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00002208 {
2209 case 'V':
2210 WRITE("guard variable for ");
Jason Molenda026aa492014-10-15 22:11:15 +00002211 if (!ParseName(true))
2212 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002213 break;
2214 case 'R':
2215 WRITE("reference temporary for ");
Jason Molenda026aa492014-10-15 22:11:15 +00002216 if (!ParseName(true))
2217 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002218 break;
2219 default:
2220#ifdef DEBUG_FAILURES
2221 printf("*** Unknown G encoding\n");
2222#endif
2223 return false;
2224 }
2225 return true;
2226 }
Jason Molenda026aa492014-10-15 22:11:15 +00002227
Kate Stonee2b21862014-07-22 17:03:38 +00002228 // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types
Jason Molenda026aa492014-10-15 22:11:15 +00002229
2230 bool
2231 ParseFunctionArgs(NameState & name_state, int return_insert_cookie)
Kate Stonee2b21862014-07-22 17:03:38 +00002232 {
Jason Molenda026aa492014-10-15 22:11:15 +00002233 char next = *m_read_ptr;
2234 if (next == 'E' || next == '\0' || next == '.')
2235 return true;
2236
Kate Stonee2b21862014-07-22 17:03:38 +00002237 // Clang has a bad habit of making unique manglings by just sticking numbers on the end of a symbol,
2238 // which is ambiguous with malformed source name manglings
Jason Molenda026aa492014-10-15 22:11:15 +00002239 const char *before_clang_uniquing_test = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002240 if (TryParseNumber())
2241 {
Jason Molenda026aa492014-10-15 22:11:15 +00002242 if (*m_read_ptr == '\0')
2243 return true;
2244 m_read_ptr = before_clang_uniquing_test;
Kate Stonee2b21862014-07-22 17:03:38 +00002245 }
Jason Molenda026aa492014-10-15 22:11:15 +00002246
Kate Stonee2b21862014-07-22 17:03:38 +00002247 if (name_state.is_last_generic && !name_state.has_no_return_type)
2248 {
2249 int return_type_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00002250 if (!ParseType())
2251 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002252 Write(' ');
2253 ReorderRange(EndRange(return_type_start_cookie),
2254 return_insert_cookie);
2255 }
Jason Molenda026aa492014-10-15 22:11:15 +00002256
Kate Stonee2b21862014-07-22 17:03:38 +00002257 Write('(');
2258 bool first_param = true;
2259 while (true)
2260 {
Jason Molenda026aa492014-10-15 22:11:15 +00002261 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002262 {
2263 case '\0':
2264 case 'E':
2265 case '.':
2266 break;
2267 case 'v':
Jason Molenda026aa492014-10-15 22:11:15 +00002268 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002269 continue;
2270 case '_':
2271 // Not a formal part of the mangling specification, but clang emits suffixes starting with _block_invoke
Jason Molenda026aa492014-10-15 22:11:15 +00002272 if (strncmp(m_read_ptr, "_block_invoke", 13) == 0)
Kate Stonee2b21862014-07-22 17:03:38 +00002273 {
Jason Molenda026aa492014-10-15 22:11:15 +00002274 m_read_ptr += strlen(m_read_ptr);
Kate Stonee2b21862014-07-22 17:03:38 +00002275 break;
2276 }
2277 // fallthrough
2278 default:
Jason Molenda026aa492014-10-15 22:11:15 +00002279 if (first_param)
2280 first_param = false;
Kate Stonee2b21862014-07-22 17:03:38 +00002281 else WriteCommaSpace();
Jason Molenda026aa492014-10-15 22:11:15 +00002282
2283 if (!ParseType())
2284 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002285 continue;
2286 }
2287 break;
2288 }
2289 Write(')');
2290 return true;
2291 }
Jason Molenda026aa492014-10-15 22:11:15 +00002292
Kate Stonee2b21862014-07-22 17:03:38 +00002293 // <encoding> ::= <function name> <bare-function-type>
2294 // ::= <data name>
2295 // ::= <special-name>
Jason Molenda026aa492014-10-15 22:11:15 +00002296
2297 bool
2298 ParseEncoding()
Kate Stonee2b21862014-07-22 17:03:38 +00002299 {
Jason Molenda026aa492014-10-15 22:11:15 +00002300 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002301 {
2302 case 'T':
Jason Molenda026aa492014-10-15 22:11:15 +00002303 ++m_read_ptr;
2304 if (!ParseSpecialNameT())
2305 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002306 break;
2307 case 'G':
Jason Molenda026aa492014-10-15 22:11:15 +00002308 ++m_read_ptr;
2309 if (!ParseSpecialNameG())
2310 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002311 break;
2312 default:
Jason Molenda026aa492014-10-15 22:11:15 +00002313 if (!ParseName(true))
2314 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002315 break;
2316 }
2317 return true;
2318 }
Jason Molenda026aa492014-10-15 22:11:15 +00002319
2320 bool
2321 ParseMangling(const char *mangled_name, long mangled_name_length = 0)
Kate Stonee2b21862014-07-22 17:03:38 +00002322 {
Jason Molenda026aa492014-10-15 22:11:15 +00002323 if (!mangled_name_length)
2324 mangled_name_length = strlen(mangled_name);
2325 m_read_end = mangled_name + mangled_name_length;
2326 m_read_ptr = mangled_name;
2327 m_write_ptr = m_buffer;
2328 m_next_substitute_index = 0;
2329 m_next_template_arg_index = m_rewrite_ranges_size - 1;
2330
2331 if (*m_read_ptr++ != '_' || *m_read_ptr++ != 'Z')
Kate Stonee2b21862014-07-22 17:03:38 +00002332 {
2333#ifdef DEBUG_FAILURES
2334 printf("*** Missing _Z prefix\n");
2335#endif
2336 return false;
2337 }
Jason Molenda026aa492014-10-15 22:11:15 +00002338 if (!ParseEncoding())
2339 return false;
2340 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002341 {
2342 case '.':
2343 Write(' ');
2344 Write('(');
Jason Molenda026aa492014-10-15 22:11:15 +00002345 Write(m_read_ptr, m_read_end - m_read_ptr);
Kate Stonee2b21862014-07-22 17:03:38 +00002346 Write(')');
2347 case '\0':
2348 return true;
2349 default:
2350#ifdef DEBUG_FAILURES
2351 printf("*** Unparsed mangled content\n");
2352#endif
2353 return false;
2354 }
2355 }
Jason Molenda026aa492014-10-15 22:11:15 +00002356
Kate Stonee2b21862014-07-22 17:03:38 +00002357private:
Jason Molenda026aa492014-10-15 22:11:15 +00002358
Kate Stonee2b21862014-07-22 17:03:38 +00002359 // External scratch storage used during demanglings
Jason Molenda026aa492014-10-15 22:11:15 +00002360
2361 char *m_buffer;
2362 const char *m_buffer_end;
2363 BufferRange *m_rewrite_ranges;
2364 int m_rewrite_ranges_size;
2365 bool m_owns_buffer;
2366 bool m_owns_m_rewrite_ranges;
2367
Kate Stonee2b21862014-07-22 17:03:38 +00002368 // Internal state used during demangling
Jason Molenda026aa492014-10-15 22:11:15 +00002369
2370 const char *m_read_ptr;
2371 const char *m_read_end;
2372 char *m_write_ptr;
2373 int m_next_template_arg_index;
2374 int m_next_substitute_index;
Kate Stonee2b21862014-07-22 17:03:38 +00002375};
2376
2377} // Anonymous namespace
2378
2379// Public entry points referenced from Mangled.cpp
2380namespace lldb_private
2381{
Jason Molenda026aa492014-10-15 22:11:15 +00002382 char *
2383 FastDemangle(const char *mangled_name)
Kate Stonee2b21862014-07-22 17:03:38 +00002384 {
2385 char buffer[16384];
Jason Molenda026aa492014-10-15 22:11:15 +00002386 SymbolDemangler demangler(buffer, sizeof (buffer));
Kate Stonee2b21862014-07-22 17:03:38 +00002387 return demangler.GetDemangledCopy(mangled_name);
2388 }
2389
Jason Molenda026aa492014-10-15 22:11:15 +00002390 char *
2391 FastDemangle(const char *mangled_name, long mangled_name_length)
Kate Stonee2b21862014-07-22 17:03:38 +00002392 {
2393 char buffer[16384];
Jason Molenda026aa492014-10-15 22:11:15 +00002394 SymbolDemangler demangler(buffer, sizeof (buffer));
Kate Stonee2b21862014-07-22 17:03:38 +00002395 return demangler.GetDemangledCopy(mangled_name, mangled_name_length);
2396 }
2397} // lldb_private namespace