blob: c46fb953dda9c6102a1c9578420c971e4505b957 [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
Jason Molenda62e06812016-02-16 04:14:33 +000014#include "lldb/lldb-private.h"
15
Kate Stonee2b21862014-07-22 17:03:38 +000016//#define DEBUG_FAILURES 1
17//#define DEBUG_SUBSTITUTIONS 1
18//#define DEBUG_TEMPLATE_ARGS 1
19//#define DEBUG_HIGHWATER 1
20//#define DEBUG_REORDERING 1
21
22namespace {
Jason Molenda026aa492014-10-15 22:11:15 +000023
Kate Stonee2b21862014-07-22 17:03:38 +000024/// @brief Represents the collection of qualifiers on a type
25
26enum Qualifiers
27{
28 QualifierNone = 0,
29 QualifierConst = 1,
30 QualifierRestrict = 2,
31 QualifierVolatile = 4,
32 QualifierReference = 8,
33 QualifierRValueReference = 16,
34 QualifierPointer = 32
35};
36
37/// @brief Categorizes the recognized operators
38
39enum class OperatorKind
40{
41 Unary,
42 Postfix,
43 Binary,
44 Ternary,
45 Other,
46 ConversionOperator,
47 Vendor,
48 NoMatch
49};
50
51/// @brief Represents one of the recognized two-character operator
52/// abbreviations used when parsing operators as names and expressions
53
54struct Operator
55{
Jason Molenda026aa492014-10-15 22:11:15 +000056 const char *name;
Kate Stonee2b21862014-07-22 17:03:38 +000057 OperatorKind kind;
58};
59
60/// @brief Represents a range of characters in the output buffer, typically for
61/// use with RewriteRange()
62
63struct BufferRange
64{
65 int offset;
66 int length;
67};
68
69/// @brief Transient state required while parsing a name
70
71struct NameState
72{
73 bool parse_function_params;
74 bool is_last_generic;
75 bool has_no_return_type;
76 BufferRange last_name_range;
77};
78
79/// @brief LLDB's fast C++ demangler
80///
81/// This is an incomplete implementation designed to speed up the demangling
82/// process that is often a bottleneck when LLDB stops a process for the first
83/// time. Where the implementation doesn't know how to demangle a symbol it
84/// fails gracefully to allow the caller to fall back to the existing demangler.
85///
86/// Over time the full mangling spec should be supported without compromising
87/// performance for the most common cases.
88
89class SymbolDemangler
90{
91public:
Jason Molenda026aa492014-10-15 22:11:15 +000092
Kate Stonee2b21862014-07-22 17:03:38 +000093 //----------------------------------------------------
94 // Public API
95 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +000096
Kate Stonee2b21862014-07-22 17:03:38 +000097 /// @brief Create a SymbolDemangler
98 ///
99 /// The newly created demangler allocates and owns scratch memory sufficient
100 /// for demangling typical symbols. Additional memory will be allocated if
101 /// needed and managed by the demangler instance.
Jason Molenda026aa492014-10-15 22:11:15 +0000102
Kate Stonee2b21862014-07-22 17:03:38 +0000103 SymbolDemangler()
104 {
Jason Molenda026aa492014-10-15 22:11:15 +0000105 m_buffer = (char *) malloc(8192);
106 m_buffer_end = m_buffer + 8192;
107 m_owns_buffer = true;
108
109 m_rewrite_ranges = (BufferRange *) malloc(128 * sizeof (BufferRange));
110 m_rewrite_ranges_size = 128;
111 m_owns_m_rewrite_ranges = true;
Kate Stonee2b21862014-07-22 17:03:38 +0000112 }
Jason Molenda026aa492014-10-15 22:11:15 +0000113
Kate Stonee2b21862014-07-22 17:03:38 +0000114 /// @brief Create a SymbolDemangler that uses provided scratch memory
115 ///
116 /// The provided memory is not owned by the demangler. It will be
117 /// overwritten during calls to GetDemangledCopy() but can be used for
118 /// other purposes between calls. The provided memory will not be freed
119 /// when this instance is destroyed.
120 ///
121 /// If demangling a symbol requires additional space it will be allocated
122 /// and managed by the demangler instance.
123 ///
124 /// @param storage_ptr Valid pointer to at least storage_size bytes of
125 /// space that the SymbolDemangler can use during demangling
126 ///
127 /// @param storage_size Number of bytes of space available scratch memory
128 /// referenced by storage_ptr
Jason Molenda026aa492014-10-15 22:11:15 +0000129
130 SymbolDemangler(void *storage_ptr, int storage_size)
Kate Stonee2b21862014-07-22 17:03:38 +0000131 {
132 // Use up to 1/8th of the provided space for rewrite ranges
Jason Molenda026aa492014-10-15 22:11:15 +0000133 m_rewrite_ranges_size = (storage_size >> 3) / sizeof (BufferRange);
134 m_rewrite_ranges = (BufferRange *) storage_ptr;
135 m_owns_m_rewrite_ranges = false;
136
Kate Stonee2b21862014-07-22 17:03:38 +0000137 // Use the rest for the character buffer
Jason Molenda026aa492014-10-15 22:11:15 +0000138 m_buffer = (char *) storage_ptr + m_rewrite_ranges_size * sizeof (BufferRange);
139 m_buffer_end = (const char *)storage_ptr + storage_size;
140 m_owns_buffer = false;
Kate Stonee2b21862014-07-22 17:03:38 +0000141 }
Jason Molenda026aa492014-10-15 22:11:15 +0000142
Kate Stonee2b21862014-07-22 17:03:38 +0000143 /// @brief Destroys the SymbolDemangler and deallocates any scratch
144 /// memory that it owns
Jason Molenda026aa492014-10-15 22:11:15 +0000145
Kate Stonee2b21862014-07-22 17:03:38 +0000146 ~SymbolDemangler()
147 {
Jason Molenda026aa492014-10-15 22:11:15 +0000148 if (m_owns_buffer)
149 free(m_buffer);
150 if (m_owns_m_rewrite_ranges)
151 free(m_rewrite_ranges);
Kate Stonee2b21862014-07-22 17:03:38 +0000152 }
Jason Molenda026aa492014-10-15 22:11:15 +0000153
Kate Stonee2b21862014-07-22 17:03:38 +0000154#ifdef DEBUG_HIGHWATER
155 int highwater_store = 0;
156 int highwater_buffer = 0;
157#endif
Jason Molenda026aa492014-10-15 22:11:15 +0000158
Kate Stonee2b21862014-07-22 17:03:38 +0000159 /// @brief Parses the provided mangled name and returns a newly allocated
160 /// demangling
161 ///
162 /// @param mangled_name Valid null-terminated C++ mangled name following
163 /// the Itanium C++ ABI mangling specification as implemented by Clang
164 ///
165 /// @result Newly allocated null-terminated demangled name when demangling
Bruce Mitchenere171da52015-07-22 00:16:02 +0000166 /// is successful, and nullptr when demangling fails. The caller is
Kate Stonee2b21862014-07-22 17:03:38 +0000167 /// responsible for freeing the allocated memory.
Jason Molenda026aa492014-10-15 22:11:15 +0000168
169 char *
170 GetDemangledCopy(const char *mangled_name,
171 long mangled_name_length = 0)
Kate Stonee2b21862014-07-22 17:03:38 +0000172 {
Jason Molenda026aa492014-10-15 22:11:15 +0000173 if (!ParseMangling(mangled_name, mangled_name_length))
174 return nullptr;
175
Kate Stonee2b21862014-07-22 17:03:38 +0000176#ifdef DEBUG_HIGHWATER
Jason Molenda026aa492014-10-15 22:11:15 +0000177 int rewrite_count = m_next_substitute_index +
178 (m_rewrite_ranges_size - 1 - m_next_template_arg_index);
179 int buffer_size = (int)(m_write_ptr - m_buffer);
180 if (rewrite_count > highwater_store)
181 highwater_store = rewrite_count;
182 if (buffer_size > highwater_buffer)
183 highwater_buffer = buffer_size;
Kate Stonee2b21862014-07-22 17:03:38 +0000184#endif
Jason Molenda026aa492014-10-15 22:11:15 +0000185
186 int length = (int)(m_write_ptr - m_buffer);
187 char *copy = (char *)malloc(length + 1);
188 memcpy(copy, m_buffer, length);
Kate Stonee2b21862014-07-22 17:03:38 +0000189 copy[length] = '\0';
190 return copy;
191 }
Jason Molenda026aa492014-10-15 22:11:15 +0000192
Kate Stonee2b21862014-07-22 17:03:38 +0000193private:
Jason Molenda026aa492014-10-15 22:11:15 +0000194
Kate Stonee2b21862014-07-22 17:03:38 +0000195 //----------------------------------------------------
196 // Grow methods
197 //
198 // Manage the storage used during demangling
199 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000200
Kate Stonee2b21862014-07-22 17:03:38 +0000201 void GrowBuffer(long min_growth = 0)
202 {
203 // By default, double the size of the buffer
Jason Molenda026aa492014-10-15 22:11:15 +0000204 long growth = m_buffer_end - m_buffer;
205
Kate Stonee2b21862014-07-22 17:03:38 +0000206 // Avoid growing by more than 1MB at a time
Jason Molenda026aa492014-10-15 22:11:15 +0000207 if (growth > 1 << 20)
208 growth = 1 << 20;
209
Kate Stonee2b21862014-07-22 17:03:38 +0000210 // ... but never grow by less than requested,
211 // or 1K, whichever is greater
Jason Molenda026aa492014-10-15 22:11:15 +0000212 if (min_growth < 1024)
213 min_growth = 1024;
214 if (growth < min_growth)
215 growth = min_growth;
216
217 // Allocate the new m_buffer and migrate content
218 long new_size = (m_buffer_end - m_buffer) + growth;
219 char *new_buffer = (char *) malloc(new_size);
220 memcpy(new_buffer, m_buffer, m_write_ptr - m_buffer);
221 if (m_owns_buffer)
222 free(m_buffer);
223 m_owns_buffer = true;
224
Kate Stonee2b21862014-07-22 17:03:38 +0000225 // Update references to the new buffer
Jason Molenda026aa492014-10-15 22:11:15 +0000226 m_write_ptr = new_buffer + (m_write_ptr - m_buffer);
227 m_buffer = new_buffer;
228 m_buffer_end = m_buffer + new_size;
Kate Stonee2b21862014-07-22 17:03:38 +0000229 }
Jason Molenda026aa492014-10-15 22:11:15 +0000230
231 void
232 GrowRewriteRanges()
Kate Stonee2b21862014-07-22 17:03:38 +0000233 {
234 // By default, double the size of the array
Jason Molenda026aa492014-10-15 22:11:15 +0000235 int growth = m_rewrite_ranges_size;
236
Kate Stonee2b21862014-07-22 17:03:38 +0000237 // Apply reasonable minimum and maximum sizes for growth
Jason Molenda026aa492014-10-15 22:11:15 +0000238 if (growth > 128)
239 growth = 128;
240 if (growth < 16)
241 growth = 16;
242
Kate Stonee2b21862014-07-22 17:03:38 +0000243 // Allocate the new array and migrate content
Jason Molenda026aa492014-10-15 22:11:15 +0000244 int bytes = (m_rewrite_ranges_size + growth) * sizeof (BufferRange);
245 BufferRange *new_ranges = (BufferRange *) malloc (bytes);
246 for (int index = 0; index < m_next_substitute_index; index++)
Kate Stonee2b21862014-07-22 17:03:38 +0000247 {
Jason Molenda026aa492014-10-15 22:11:15 +0000248 new_ranges[index] = m_rewrite_ranges[index];
Kate Stonee2b21862014-07-22 17:03:38 +0000249 }
Jason Molenda026aa492014-10-15 22:11:15 +0000250 for (int index = m_rewrite_ranges_size - 1;
251 index > m_next_template_arg_index; index--)
Kate Stonee2b21862014-07-22 17:03:38 +0000252 {
Jason Molenda026aa492014-10-15 22:11:15 +0000253 new_ranges[index + growth] = m_rewrite_ranges[index];
Kate Stonee2b21862014-07-22 17:03:38 +0000254 }
Jason Molenda026aa492014-10-15 22:11:15 +0000255 if (m_owns_m_rewrite_ranges)
256 free(m_rewrite_ranges);
257 m_owns_m_rewrite_ranges = true;
258
Kate Stonee2b21862014-07-22 17:03:38 +0000259 // Update references to the new array
Jason Molenda026aa492014-10-15 22:11:15 +0000260 m_rewrite_ranges = new_ranges;
261 m_rewrite_ranges_size += growth;
262 m_next_template_arg_index += growth;
Kate Stonee2b21862014-07-22 17:03:38 +0000263 }
Jason Molenda026aa492014-10-15 22:11:15 +0000264
Kate Stonee2b21862014-07-22 17:03:38 +0000265 //----------------------------------------------------
266 // Range and state management
267 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000268
269 int
270 GetStartCookie()
Kate Stonee2b21862014-07-22 17:03:38 +0000271 {
Jason Molenda026aa492014-10-15 22:11:15 +0000272 return (int)(m_write_ptr - m_buffer);
Kate Stonee2b21862014-07-22 17:03:38 +0000273 }
Jason Molenda026aa492014-10-15 22:11:15 +0000274
275 BufferRange
276 EndRange(int start_cookie)
Kate Stonee2b21862014-07-22 17:03:38 +0000277 {
Jason Molenda026aa492014-10-15 22:11:15 +0000278 return { start_cookie, (int)(m_write_ptr - (m_buffer + start_cookie)) };
Kate Stonee2b21862014-07-22 17:03:38 +0000279 }
Jason Molenda026aa492014-10-15 22:11:15 +0000280
281 void
282 ReorderRange(BufferRange source_range, int insertion_point_cookie)
Kate Stonee2b21862014-07-22 17:03:38 +0000283 {
284 // Ensure there's room the preserve the source range
Jason Molenda026aa492014-10-15 22:11:15 +0000285 if (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 GrowBuffer(m_write_ptr + source_range.length - m_buffer_end);
Kate Stonee2b21862014-07-22 17:03:38 +0000288 }
Jason Molenda026aa492014-10-15 22:11:15 +0000289
Kate Stonee2b21862014-07-22 17:03:38 +0000290 // Reorder the content
Jason Molenda026aa492014-10-15 22:11:15 +0000291 memcpy(m_write_ptr, m_buffer + source_range.offset, source_range.length);
292 memmove(m_buffer + insertion_point_cookie + source_range.length,
293 m_buffer + insertion_point_cookie,
Kate Stonee2b21862014-07-22 17:03:38 +0000294 source_range.offset - insertion_point_cookie);
Jason Molenda026aa492014-10-15 22:11:15 +0000295 memcpy(m_buffer + insertion_point_cookie, m_write_ptr, source_range.length);
296
Kate Stonee2b21862014-07-22 17:03:38 +0000297 // Fix up rewritable ranges, covering both substitutions and templates
298 int index = 0;
299 while (true)
300 {
Jason Molenda026aa492014-10-15 22:11:15 +0000301 if (index == m_next_substitute_index)
302 index = m_next_template_arg_index + 1;
303 if (index == m_rewrite_ranges_size)
304 break;
305
Kate Stonee2b21862014-07-22 17:03:38 +0000306 // Affected ranges are either shuffled forward when after the
307 // insertion but before the source, or backward when inside the
308 // source
Jason Molenda026aa492014-10-15 22:11:15 +0000309 int candidate_offset = m_rewrite_ranges[index].offset;
Kate Stonee2b21862014-07-22 17:03:38 +0000310 if (candidate_offset >= insertion_point_cookie)
311 {
312 if (candidate_offset < source_range.offset)
313 {
Jason Molenda026aa492014-10-15 22:11:15 +0000314 m_rewrite_ranges[index].offset += source_range.length;
Kate Stonee2b21862014-07-22 17:03:38 +0000315 }
316 else if (candidate_offset >= source_range.offset)
317 {
Jason Molenda026aa492014-10-15 22:11:15 +0000318 m_rewrite_ranges[index].offset -= (source_range.offset - insertion_point_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +0000319 }
320 }
321 ++index;
322 }
323 }
Jason Molenda026aa492014-10-15 22:11:15 +0000324
325 void
326 EndSubstitution(int start_cookie)
Kate Stonee2b21862014-07-22 17:03:38 +0000327 {
Jason Molenda026aa492014-10-15 22:11:15 +0000328 if (m_next_substitute_index == m_next_template_arg_index)
329 GrowRewriteRanges();
330
331 int index = m_next_substitute_index++;
332 m_rewrite_ranges[index] = EndRange(start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +0000333#ifdef DEBUG_SUBSTITUTIONS
334 printf("Saved substitution # %d = %.*s\n", index,
Jason Molenda026aa492014-10-15 22:11:15 +0000335 m_rewrite_ranges[index].length, m_buffer + start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +0000336#endif
337 }
Jason Molenda026aa492014-10-15 22:11:15 +0000338
339 void
340 EndTemplateArg(int start_cookie)
Kate Stonee2b21862014-07-22 17:03:38 +0000341 {
Jason Molenda026aa492014-10-15 22:11:15 +0000342 if (m_next_substitute_index == m_next_template_arg_index)
343 GrowRewriteRanges();
344
345 int index = m_next_template_arg_index--;
346 m_rewrite_ranges[index] = EndRange(start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +0000347#ifdef DEBUG_TEMPLATE_ARGS
348 printf("Saved template arg # %d = %.*s\n",
Jason Molenda026aa492014-10-15 22:11:15 +0000349 m_rewrite_ranges_size - index - 1,
350 m_rewrite_ranges[index].length, m_buffer + start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +0000351#endif
352 }
Jason Molenda026aa492014-10-15 22:11:15 +0000353
354 void
355 ResetTemplateArgs()
Kate Stonee2b21862014-07-22 17:03:38 +0000356 {
357 //TODO: this works, but is it the right thing to do?
358 // Should we push/pop somehow at the call sites?
Jason Molenda026aa492014-10-15 22:11:15 +0000359 m_next_template_arg_index = m_rewrite_ranges_size - 1;
Kate Stonee2b21862014-07-22 17:03:38 +0000360 }
Jason Molenda026aa492014-10-15 22:11:15 +0000361
Kate Stonee2b21862014-07-22 17:03:38 +0000362 //----------------------------------------------------
363 // Write methods
364 //
365 // Appends content to the existing output buffer
366 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000367
368 void
369 Write(char character)
Kate Stonee2b21862014-07-22 17:03:38 +0000370 {
Jason Molenda026aa492014-10-15 22:11:15 +0000371 if (m_write_ptr == m_buffer_end)
372 GrowBuffer();
373 *m_write_ptr++ = character;
Kate Stonee2b21862014-07-22 17:03:38 +0000374 }
Jason Molenda026aa492014-10-15 22:11:15 +0000375
376 void
377 Write(const char *content)
Kate Stonee2b21862014-07-22 17:03:38 +0000378 {
379 Write(content, strlen(content));
380 }
Jason Molenda026aa492014-10-15 22:11:15 +0000381
382 void
383 Write(const char *content, long content_length)
Kate Stonee2b21862014-07-22 17:03:38 +0000384 {
Jason Molenda026aa492014-10-15 22:11:15 +0000385 char *end_m_write_ptr = m_write_ptr + content_length;
386 if (end_m_write_ptr > m_buffer_end)
Kate Stonee2b21862014-07-22 17:03:38 +0000387 {
Jason Molendaebd01b02015-04-30 23:42:56 +0000388 if (content >= m_buffer && content < m_buffer_end)
389 {
390 long offset = content - m_buffer;
391 GrowBuffer (end_m_write_ptr - m_buffer_end);
392 content = m_buffer + offset;
393 }
394 else
395 {
396 GrowBuffer (end_m_write_ptr - m_buffer_end);
397 }
Jason Molenda026aa492014-10-15 22:11:15 +0000398 end_m_write_ptr = m_write_ptr + content_length;
Kate Stonee2b21862014-07-22 17:03:38 +0000399 }
Jason Molendaebd01b02015-04-30 23:42:56 +0000400 memcpy (m_write_ptr, content, content_length);
Jason Molenda026aa492014-10-15 22:11:15 +0000401 m_write_ptr = end_m_write_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000402 }
Jason Molenda026aa492014-10-15 22:11:15 +0000403#define WRITE(x) Write(x, sizeof (x) - 1)
404
405 void
406 WriteTemplateStart()
Kate Stonee2b21862014-07-22 17:03:38 +0000407 {
408 Write('<');
409 }
Jason Molenda026aa492014-10-15 22:11:15 +0000410
411 void
412 WriteTemplateEnd()
Kate Stonee2b21862014-07-22 17:03:38 +0000413 {
414 // Put a space between terminal > characters when nesting templates
Jason Molenda026aa492014-10-15 22:11:15 +0000415 if (m_write_ptr != m_buffer && *(m_write_ptr - 1) == '>')
416 WRITE(" >");
Kate Stonee2b21862014-07-22 17:03:38 +0000417 else Write('>');
418 }
Jason Molenda026aa492014-10-15 22:11:15 +0000419
420 void
421 WriteCommaSpace()
Kate Stonee2b21862014-07-22 17:03:38 +0000422 {
423 WRITE(", ");
424 }
Jason Molenda026aa492014-10-15 22:11:15 +0000425
426 void
427 WriteNamespaceSeparator()
Kate Stonee2b21862014-07-22 17:03:38 +0000428 {
429 WRITE("::");
430 }
Jason Molenda026aa492014-10-15 22:11:15 +0000431
432 void
433 WriteStdPrefix()
Kate Stonee2b21862014-07-22 17:03:38 +0000434 {
435 WRITE("std::");
436 }
Jason Molenda026aa492014-10-15 22:11:15 +0000437
438 void
439 WriteQualifiers(int qualifiers, bool space_before_reference = true)
Kate Stonee2b21862014-07-22 17:03:38 +0000440 {
Jason Molenda026aa492014-10-15 22:11:15 +0000441 if (qualifiers & QualifierPointer)
442 Write('*');
443 if (qualifiers & QualifierConst)
444 WRITE(" const");
445 if (qualifiers & QualifierVolatile)
446 WRITE(" volatile");
447 if (qualifiers & QualifierRestrict)
448 WRITE(" restrict");
Kate Stonee2b21862014-07-22 17:03:38 +0000449 if (qualifiers & QualifierReference)
450 {
Jason Molenda026aa492014-10-15 22:11:15 +0000451 if (space_before_reference)
452 WRITE(" &");
Kate Stonee2b21862014-07-22 17:03:38 +0000453 else Write('&');
454 }
455 if (qualifiers & QualifierRValueReference)
456 {
Jason Molenda026aa492014-10-15 22:11:15 +0000457 if (space_before_reference)
458 WRITE(" &&");
Kate Stonee2b21862014-07-22 17:03:38 +0000459 else WRITE("&&");
460 }
461 }
Jason Molenda026aa492014-10-15 22:11:15 +0000462
Kate Stonee2b21862014-07-22 17:03:38 +0000463 //----------------------------------------------------
464 // Rewrite methods
465 //
466 // Write another copy of content already present
467 // earlier in the output buffer
468 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000469
470 void
471 RewriteRange(BufferRange range)
Kate Stonee2b21862014-07-22 17:03:38 +0000472 {
Jason Molenda026aa492014-10-15 22:11:15 +0000473 Write(m_buffer + range.offset, range.length);
Kate Stonee2b21862014-07-22 17:03:38 +0000474 }
Jason Molenda026aa492014-10-15 22:11:15 +0000475
476 bool
477 RewriteSubstitution(int index)
Kate Stonee2b21862014-07-22 17:03:38 +0000478 {
Jason Molenda026aa492014-10-15 22:11:15 +0000479 if (index < 0 || index >= m_next_substitute_index)
Kate Stonee2b21862014-07-22 17:03:38 +0000480 {
481#ifdef DEBUG_FAILURES
482 printf("*** Invalid substitution #%d\n", index);
483#endif
484 return false;
485 }
Jason Molenda026aa492014-10-15 22:11:15 +0000486 RewriteRange(m_rewrite_ranges[index]);
Kate Stonee2b21862014-07-22 17:03:38 +0000487 return true;
488 }
Jason Molenda026aa492014-10-15 22:11:15 +0000489
490 bool
491 RewriteTemplateArg(int template_index)
Kate Stonee2b21862014-07-22 17:03:38 +0000492 {
Jason Molenda026aa492014-10-15 22:11:15 +0000493 int index = m_rewrite_ranges_size - 1 - template_index;
494 if (template_index < 0 || index <= m_next_template_arg_index)
Kate Stonee2b21862014-07-22 17:03:38 +0000495 {
496#ifdef DEBUG_FAILURES
497 printf("*** Invalid template arg reference #%d\n", template_index);
498#endif
499 return false;
500 }
Jason Molenda026aa492014-10-15 22:11:15 +0000501 RewriteRange(m_rewrite_ranges[index]);
Kate Stonee2b21862014-07-22 17:03:38 +0000502 return true;
503 }
Jason Molenda026aa492014-10-15 22:11:15 +0000504
Kate Stonee2b21862014-07-22 17:03:38 +0000505 //----------------------------------------------------
506 // TryParse methods
507 //
508 // Provide information with return values instead of
509 // writing to the output buffer
510 //
511 // Values indicating failure guarantee that the pre-
Jason Molenda026aa492014-10-15 22:11:15 +0000512 // call m_read_ptr is unchanged
Kate Stonee2b21862014-07-22 17:03:38 +0000513 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000514
515 int
516 TryParseNumber()
Kate Stonee2b21862014-07-22 17:03:38 +0000517 {
Jason Molenda026aa492014-10-15 22:11:15 +0000518 unsigned char digit = *m_read_ptr - '0';
519 if (digit > 9)
520 return -1;
521
Kate Stonee2b21862014-07-22 17:03:38 +0000522 int count = digit;
523 while (true)
524 {
Jason Molenda026aa492014-10-15 22:11:15 +0000525 digit = *++m_read_ptr - '0';
526 if (digit > 9)
527 break;
528
Kate Stonee2b21862014-07-22 17:03:38 +0000529 count = count * 10 + digit;
530 }
531 return count;
532 }
Jason Molenda026aa492014-10-15 22:11:15 +0000533
534 int
535 TryParseBase36Number()
Kate Stonee2b21862014-07-22 17:03:38 +0000536 {
Jason Molenda026aa492014-10-15 22:11:15 +0000537 char digit = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000538 int count;
Jason Molenda026aa492014-10-15 22:11:15 +0000539 if (digit >= '0' && digit <= '9')
540 count = digit -= '0';
541 else if (digit >= 'A' && digit <= 'Z')
542 count = digit -= ('A' - 10);
Kate Stonee2b21862014-07-22 17:03:38 +0000543 else return -1;
Jason Molenda026aa492014-10-15 22:11:15 +0000544
Kate Stonee2b21862014-07-22 17:03:38 +0000545 while (true)
546 {
Jason Molenda026aa492014-10-15 22:11:15 +0000547 digit = *++m_read_ptr;
548 if (digit >= '0' && digit <= '9')
549 digit -= '0';
550 else if (digit >= 'A' && digit <= 'Z')
551 digit -= ('A' - 10);
Kate Stonee2b21862014-07-22 17:03:38 +0000552 else break;
Jason Molenda026aa492014-10-15 22:11:15 +0000553
Kate Stonee2b21862014-07-22 17:03:38 +0000554 count = count * 36 + digit;
555 }
556 return count;
557 }
Jason Molenda026aa492014-10-15 22:11:15 +0000558
Kate Stonee2b21862014-07-22 17:03:38 +0000559 // <builtin-type> ::= v # void
560 // ::= w # wchar_t
561 // ::= b # bool
562 // ::= c # char
563 // ::= a # signed char
564 // ::= h # unsigned char
565 // ::= s # short
566 // ::= t # unsigned short
567 // ::= i # int
568 // ::= j # unsigned int
569 // ::= l # long
570 // ::= m # unsigned long
571 // ::= x # long long, __int64
572 // ::= y # unsigned long long, __int64
573 // ::= n # __int128
574 // ::= o # unsigned __int128
575 // ::= f # float
576 // ::= d # double
577 // ::= e # long double, __float80
578 // ::= g # __float128
579 // ::= z # ellipsis
580 // ::= Dd # IEEE 754r decimal floating point (64 bits)
581 // ::= De # IEEE 754r decimal floating point (128 bits)
582 // ::= Df # IEEE 754r decimal floating point (32 bits)
583 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
584 // ::= Di # char32_t
585 // ::= Ds # char16_t
586 // ::= Da # auto (in dependent new-expressions)
587 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
588 // ::= u <source-name> # vendor extended type
Jason Molenda026aa492014-10-15 22:11:15 +0000589
590 const char *
591 TryParseBuiltinType()
Kate Stonee2b21862014-07-22 17:03:38 +0000592 {
Jason Molenda026aa492014-10-15 22:11:15 +0000593 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000594 {
595 case 'v': return "void";
596 case 'w': return "wchar_t";
597 case 'b': return "bool";
598 case 'c': return "char";
599 case 'a': return "signed char";
600 case 'h': return "unsigned char";
601 case 's': return "short";
602 case 't': return "unsigned short";
603 case 'i': return "int";
604 case 'j': return "unsigned int";
605 case 'l': return "long";
606 case 'm': return "unsigned long";
607 case 'x': return "long long";
608 case 'y': return "unsigned long long";
609 case 'n': return "__int128";
610 case 'o': return "unsigned __int128";
611 case 'f': return "float";
612 case 'd': return "double";
613 case 'e': return "long double";
614 case 'g': return "__float128";
615 case 'z': return "...";
616 case 'D':
617 {
Jason Molenda026aa492014-10-15 22:11:15 +0000618 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000619 {
620 case 'd': return "decimal64";
621 case 'e': return "decimal128";
622 case 'f': return "decimal32";
623 case 'h': return "decimal16";
624 case 'i': return "char32_t";
625 case 's': return "char16_t";
626 case 'a': return "auto";
627 case 'c': return "decltype(auto)";
628 case 'n': return "std::nullptr_t";
629 default:
Jason Molenda026aa492014-10-15 22:11:15 +0000630 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000631 }
632 }
633 }
Jason Molenda026aa492014-10-15 22:11:15 +0000634 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000635 return nullptr;
636 }
Jason Molenda026aa492014-10-15 22:11:15 +0000637
Kate Stonee2b21862014-07-22 17:03:38 +0000638 // <operator-name>
639 // ::= aa # &&
640 // ::= ad # & (unary)
641 // ::= an # &
642 // ::= aN # &=
643 // ::= aS # =
644 // ::= cl # ()
645 // ::= cm # ,
646 // ::= co # ~
647 // ::= da # delete[]
648 // ::= de # * (unary)
649 // ::= dl # delete
650 // ::= dv # /
651 // ::= dV # /=
652 // ::= eo # ^
653 // ::= eO # ^=
654 // ::= eq # ==
655 // ::= ge # >=
656 // ::= gt # >
657 // ::= ix # []
658 // ::= le # <=
659 // ::= ls # <<
660 // ::= lS # <<=
661 // ::= lt # <
662 // ::= mi # -
663 // ::= mI # -=
664 // ::= ml # *
665 // ::= mL # *=
666 // ::= mm # -- (postfix in <expression> context)
667 // ::= na # new[]
668 // ::= ne # !=
669 // ::= ng # - (unary)
670 // ::= nt # !
671 // ::= nw # new
672 // ::= oo # ||
673 // ::= or # |
674 // ::= oR # |=
675 // ::= pm # ->*
676 // ::= pl # +
677 // ::= pL # +=
678 // ::= pp # ++ (postfix in <expression> context)
679 // ::= ps # + (unary)
680 // ::= pt # ->
681 // ::= qu # ?
682 // ::= rm # %
683 // ::= rM # %=
684 // ::= rs # >>
685 // ::= rS # >>=
686 // ::= cv <type> # (cast)
687 // ::= v <digit> <source-name> # vendor extended operator
Jason Molenda026aa492014-10-15 22:11:15 +0000688
689 Operator
690 TryParseOperator()
Kate Stonee2b21862014-07-22 17:03:38 +0000691 {
Jason Molenda026aa492014-10-15 22:11:15 +0000692 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000693 {
694 case 'a':
Jason Molenda026aa492014-10-15 22:11:15 +0000695 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000696 {
697 case 'a': return { "&&", OperatorKind::Binary };
698 case 'd': return { "&", OperatorKind::Unary };
699 case 'n': return { "&", OperatorKind::Binary };
700 case 'N': return { "&=", OperatorKind::Binary };
701 case 'S': return { "=", OperatorKind::Binary };
702 }
Jason Molenda026aa492014-10-15 22:11:15 +0000703 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000704 break;
705 case 'c':
Jason Molenda026aa492014-10-15 22:11:15 +0000706 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000707 {
708 case 'l': return { "()", OperatorKind::Other };
709 case 'm': return { ",", OperatorKind::Other };
710 case 'o': return { "~", OperatorKind::Unary };
711 case 'v': return { nullptr, OperatorKind::ConversionOperator };
712 }
Jason Molenda026aa492014-10-15 22:11:15 +0000713 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000714 break;
715 case 'd':
Jason Molenda026aa492014-10-15 22:11:15 +0000716 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000717 {
718 case 'a': return { " delete[]", OperatorKind::Other };
719 case 'e': return { "*", OperatorKind::Unary };
720 case 'l': return { " delete", OperatorKind::Other };
721 case 'v': return { "/", OperatorKind::Binary };
722 case 'V': return { "/=", OperatorKind::Binary };
723 }
Jason Molenda026aa492014-10-15 22:11:15 +0000724 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000725 break;
726 case 'e':
Jason Molenda026aa492014-10-15 22:11:15 +0000727 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000728 {
729 case 'o': return { "^", OperatorKind::Binary };
730 case 'O': return { "^=", OperatorKind::Binary };
731 case 'q': return { "==", OperatorKind::Binary };
732 }
Jason Molenda026aa492014-10-15 22:11:15 +0000733 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000734 break;
735 case 'g':
Jason Molenda026aa492014-10-15 22:11:15 +0000736 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000737 {
738 case 'e': return { ">=", OperatorKind::Binary };
739 case 't': return { ">", OperatorKind::Binary };
740 }
Jason Molenda026aa492014-10-15 22:11:15 +0000741 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000742 break;
743 case 'i':
Jason Molenda026aa492014-10-15 22:11:15 +0000744 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000745 {
746 case 'x': return { "[]", OperatorKind::Other };
747 }
Jason Molenda026aa492014-10-15 22:11:15 +0000748 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000749 break;
750 case 'l':
Jason Molenda026aa492014-10-15 22:11:15 +0000751 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000752 {
753 case 'e': return { "<=", OperatorKind::Binary };
754 case 's': return { "<<", OperatorKind::Binary };
755 case 'S': return { "<<=", OperatorKind::Binary };
756 case 't': return { "<", OperatorKind::Binary };
757 // case 'i': return { "?", OperatorKind::Binary };
758 }
Jason Molenda026aa492014-10-15 22:11:15 +0000759 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000760 break;
761 case 'm':
Jason Molenda026aa492014-10-15 22:11:15 +0000762 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000763 {
764 case 'i': return { "-", OperatorKind::Binary };
765 case 'I': return { "-=", OperatorKind::Binary };
766 case 'l': return { "*", OperatorKind::Binary };
767 case 'L': return { "*=", OperatorKind::Binary };
768 case 'm': return { "--", OperatorKind::Postfix };
769 }
Jason Molenda026aa492014-10-15 22:11:15 +0000770 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000771 break;
772 case 'n':
Jason Molenda026aa492014-10-15 22:11:15 +0000773 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000774 {
775 case 'a': return { " new[]", OperatorKind::Other };
776 case 'e': return { "!=", OperatorKind::Binary };
777 case 'g': return { "-", OperatorKind::Unary };
778 case 't': return { "!", OperatorKind::Unary };
779 case 'w': return { " new", OperatorKind::Other };
780 }
Jason Molenda026aa492014-10-15 22:11:15 +0000781 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000782 break;
783 case 'o':
Jason Molenda026aa492014-10-15 22:11:15 +0000784 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000785 {
786 case 'o': return { "||", OperatorKind::Binary };
787 case 'r': return { "|", OperatorKind::Binary };
788 case 'R': return { "|=", OperatorKind::Binary };
789 }
Jason Molenda026aa492014-10-15 22:11:15 +0000790 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000791 break;
792 case 'p':
Jason Molenda026aa492014-10-15 22:11:15 +0000793 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000794 {
795 case 'm': return { "->*", OperatorKind::Binary };
796 case 's': return { "+", OperatorKind::Unary };
797 case 'l': return { "+", OperatorKind::Binary };
798 case 'L': return { "+=", OperatorKind::Binary };
799 case 'p': return { "++", OperatorKind::Postfix };
800 case 't': return { "->", OperatorKind::Binary };
801 }
Jason Molenda026aa492014-10-15 22:11:15 +0000802 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000803 break;
804 case 'q':
Jason Molenda026aa492014-10-15 22:11:15 +0000805 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000806 {
807 case 'u': return { "?", OperatorKind::Ternary };
808 }
Jason Molenda026aa492014-10-15 22:11:15 +0000809 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000810 break;
811 case 'r':
Jason Molenda026aa492014-10-15 22:11:15 +0000812 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +0000813 {
814 case 'm': return { "%", OperatorKind::Binary };
815 case 'M': return { "%=", OperatorKind::Binary };
816 case 's': return { ">>", OperatorKind::Binary };
817 case 'S': return { ">=", OperatorKind::Binary };
818 }
Jason Molenda026aa492014-10-15 22:11:15 +0000819 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000820 break;
821 case 'v':
Jason Molenda026aa492014-10-15 22:11:15 +0000822 char digit = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000823 if (digit >= '0' && digit <= '9')
824 {
Jason Molenda026aa492014-10-15 22:11:15 +0000825 m_read_ptr++;
Kate Stonee2b21862014-07-22 17:03:38 +0000826 return { nullptr, OperatorKind::Vendor };
827 }
Jason Molenda026aa492014-10-15 22:11:15 +0000828 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000829 break;
830 }
Jason Molenda026aa492014-10-15 22:11:15 +0000831 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000832 return { nullptr, OperatorKind::NoMatch };
833 }
Jason Molenda026aa492014-10-15 22:11:15 +0000834
Kate Stonee2b21862014-07-22 17:03:38 +0000835 // <CV-qualifiers> ::= [r] [V] [K]
836 // <ref-qualifier> ::= R # & ref-qualifier
837 // <ref-qualifier> ::= O # && ref-qualifier
Jason Molenda026aa492014-10-15 22:11:15 +0000838
839 int
840 TryParseQualifiers(bool allow_cv, bool allow_ro)
Kate Stonee2b21862014-07-22 17:03:38 +0000841 {
842 int qualifiers = QualifierNone;
Jason Molenda026aa492014-10-15 22:11:15 +0000843 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000844 if (allow_cv)
845 {
846 if (next == 'r') // restrict
847 {
848 qualifiers |= QualifierRestrict;
Jason Molenda026aa492014-10-15 22:11:15 +0000849 next = *++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000850 }
851 if (next == 'V') // volatile
852 {
853 qualifiers |= QualifierVolatile;
Jason Molenda026aa492014-10-15 22:11:15 +0000854 next = *++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000855 }
856 if (next == 'K') // const
857 {
858 qualifiers |= QualifierConst;
Jason Molenda026aa492014-10-15 22:11:15 +0000859 next = *++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000860 }
861 }
862 if (allow_ro)
863 {
864 if (next == 'R')
865 {
Jason Molenda026aa492014-10-15 22:11:15 +0000866 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000867 qualifiers |= QualifierReference;
868 }
869 else if (next =='O')
870 {
Jason Molenda026aa492014-10-15 22:11:15 +0000871 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000872 qualifiers |= QualifierRValueReference;
873 }
874 }
875 return qualifiers;
876 }
Jason Molenda026aa492014-10-15 22:11:15 +0000877
Kate Stonee2b21862014-07-22 17:03:38 +0000878 // <discriminator> := _ <non-negative number> # when number < 10
879 // := __ <non-negative number> _ # when number >= 10
880 // extension := decimal-digit+
Jason Molenda026aa492014-10-15 22:11:15 +0000881
882 int
883 TryParseDiscriminator()
Kate Stonee2b21862014-07-22 17:03:38 +0000884 {
Jason Molenda026aa492014-10-15 22:11:15 +0000885 const char *discriminator_start = m_read_ptr;
886
Kate Stonee2b21862014-07-22 17:03:38 +0000887 // Test the extension first, since it's what Clang uses
888 int discriminator_value = TryParseNumber();
Jason Molenda026aa492014-10-15 22:11:15 +0000889 if (discriminator_value != -1)
890 return discriminator_value;
891
892 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000893 if (next == '_')
894 {
Jason Molenda026aa492014-10-15 22:11:15 +0000895 next = *++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000896 if (next == '_')
897 {
Jason Molenda026aa492014-10-15 22:11:15 +0000898 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000899 discriminator_value = TryParseNumber();
Jason Molenda026aa492014-10-15 22:11:15 +0000900 if (discriminator_value != -1 && *m_read_ptr++ != '_')
Kate Stonee2b21862014-07-22 17:03:38 +0000901 {
902 return discriminator_value;
903 }
904 }
905 else if (next >= '0' && next <= '9')
906 {
Jason Molenda026aa492014-10-15 22:11:15 +0000907 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000908 return next - '0';
909 }
910 }
Jason Molenda026aa492014-10-15 22:11:15 +0000911
Kate Stonee2b21862014-07-22 17:03:38 +0000912 // Not a valid discriminator
Jason Molenda026aa492014-10-15 22:11:15 +0000913 m_read_ptr = discriminator_start;
Kate Stonee2b21862014-07-22 17:03:38 +0000914 return -1;
915 }
Jason Molenda026aa492014-10-15 22:11:15 +0000916
Kate Stonee2b21862014-07-22 17:03:38 +0000917 //----------------------------------------------------
918 // Parse methods
919 //
Jason Molenda026aa492014-10-15 22:11:15 +0000920 // Consume input starting from m_read_ptr and produce
921 // buffered output at m_write_ptr
Kate Stonee2b21862014-07-22 17:03:38 +0000922 //
Jason Molenda026aa492014-10-15 22:11:15 +0000923 // Failures return false and may leave m_read_ptr in an
Kate Stonee2b21862014-07-22 17:03:38 +0000924 // indeterminate state
925 //----------------------------------------------------
Jason Molenda026aa492014-10-15 22:11:15 +0000926
927 bool
928 Parse(char character)
Kate Stonee2b21862014-07-22 17:03:38 +0000929 {
Jason Molenda026aa492014-10-15 22:11:15 +0000930 if (*m_read_ptr++ == character)
931 return true;
Kate Stonee2b21862014-07-22 17:03:38 +0000932#ifdef DEBUG_FAILURES
933 printf("*** Expected '%c'\n", character);
934#endif
935 return false;
936 }
Jason Molenda026aa492014-10-15 22:11:15 +0000937
Kate Stonee2b21862014-07-22 17:03:38 +0000938 // <number> ::= [n] <non-negative decimal integer>
Jason Molenda026aa492014-10-15 22:11:15 +0000939
940 bool
941 ParseNumber(bool allow_negative = false)
Kate Stonee2b21862014-07-22 17:03:38 +0000942 {
Jason Molenda026aa492014-10-15 22:11:15 +0000943 if (allow_negative && *m_read_ptr == 'n')
Kate Stonee2b21862014-07-22 17:03:38 +0000944 {
945 Write('-');
Jason Molenda026aa492014-10-15 22:11:15 +0000946 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000947 }
Jason Molenda026aa492014-10-15 22:11:15 +0000948 const char *before_digits = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000949 while (true)
950 {
Jason Molenda026aa492014-10-15 22:11:15 +0000951 unsigned char digit = *m_read_ptr - '0';
952 if (digit > 9)
953 break;
954 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +0000955 }
Jason Molenda026aa492014-10-15 22:11:15 +0000956 if (int digit_count = (int)(m_read_ptr - before_digits))
Kate Stonee2b21862014-07-22 17:03:38 +0000957 {
958 Write(before_digits, digit_count);
959 return true;
960 }
961#ifdef DEBUG_FAILURES
962 printf("*** Expected number\n");
963#endif
964 return false;
965 }
Jason Molenda026aa492014-10-15 22:11:15 +0000966
Kate Stonee2b21862014-07-22 17:03:38 +0000967 // <substitution> ::= S <seq-id> _
968 // ::= S_
969 // <substitution> ::= Sa # ::std::allocator
970 // <substitution> ::= Sb # ::std::basic_string
971 // <substitution> ::= Ss # ::std::basic_string < char,
972 // ::std::char_traits<char>,
973 // ::std::allocator<char> >
974 // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
975 // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
976 // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Jason Molenda026aa492014-10-15 22:11:15 +0000977
978 bool
979 ParseSubstitution()
Kate Stonee2b21862014-07-22 17:03:38 +0000980 {
Jason Molenda026aa492014-10-15 22:11:15 +0000981 const char *substitution;
982 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +0000983 {
984 case 'a': substitution = "std::allocator"; break;
985 case 'b': substitution = "std::basic_string"; break;
986 case 's': substitution = "std::string"; break;
987 case 'i': substitution = "std::istream"; break;
988 case 'o': substitution = "std::ostream"; break;
989 case 'd': substitution = "std::iostream"; break;
990 default:
991 // A failed attempt to parse a number will return -1 which turns out to be
992 // perfect here as S_ is the first substitution, S0_ the next and so forth
993 int substitution_index = TryParseBase36Number();
Jason Molenda026aa492014-10-15 22:11:15 +0000994 if (*m_read_ptr++ != '_')
Kate Stonee2b21862014-07-22 17:03:38 +0000995 {
996#ifdef DEBUG_FAILURES
997 printf("*** Expected terminal _ in substitution\n");
998#endif
999 return false;
1000 }
Jason Molenda026aa492014-10-15 22:11:15 +00001001 return RewriteSubstitution (substitution_index + 1);
Kate Stonee2b21862014-07-22 17:03:38 +00001002 }
1003 Write(substitution);
Jason Molenda026aa492014-10-15 22:11:15 +00001004 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001005 return true;
1006 }
Jason Molenda026aa492014-10-15 22:11:15 +00001007
Kate Stonee2b21862014-07-22 17:03:38 +00001008 // <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
1009 //
1010 // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types
Jason Molenda026aa492014-10-15 22:11:15 +00001011
1012 bool
1013 ParseFunctionType (int inner_qualifiers = QualifierNone)
Kate Stonee2b21862014-07-22 17:03:38 +00001014 {
1015#ifdef DEBUG_FAILURES
1016 printf("*** Function types not supported\n");
1017#endif
1018 //TODO: first steps toward an implementation follow, but they're far
1019 // from complete. Function types tend to bracket other types eg:
1020 // int (*)() when used as the type for "name" becomes int (*name)().
1021 // This makes substitution et al ... interesting.
1022 return false;
Jason Molenda026aa492014-10-15 22:11:15 +00001023
Jason Molenda61e0a3e2014-10-17 01:36:20 +00001024#if 0 // TODO
Jason Molenda026aa492014-10-15 22:11:15 +00001025 if (*m_read_ptr == 'Y')
1026 ++m_read_ptr;
1027
Kate Stonee2b21862014-07-22 17:03:38 +00001028 int return_type_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001029 if (!ParseType())
1030 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001031 Write(' ');
Jason Molenda026aa492014-10-15 22:11:15 +00001032
Kate Stonee2b21862014-07-22 17:03:38 +00001033 int insert_cookie = GetStartCookie();
1034 Write('(');
1035 bool first_param = true;
1036 int qualifiers = QualifierNone;
1037 while (true)
1038 {
Jason Molenda026aa492014-10-15 22:11:15 +00001039 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00001040 {
1041 case 'E':
Jason Molenda026aa492014-10-15 22:11:15 +00001042 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001043 Write(')');
1044 break;
1045 case 'v':
Jason Molenda026aa492014-10-15 22:11:15 +00001046 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001047 continue;
1048 case 'R':
1049 case 'O':
Jason Molenda026aa492014-10-15 22:11:15 +00001050 if (*(m_read_ptr + 1) == 'E')
Kate Stonee2b21862014-07-22 17:03:38 +00001051 {
Jason Molenda026aa492014-10-15 22:11:15 +00001052 qualifiers = TryParseQualifiers (false, true);
Kate Stonee2b21862014-07-22 17:03:38 +00001053 Parse('E');
1054 break;
1055 }
1056 // fallthrough
1057 default:
1058 {
Jason Molenda026aa492014-10-15 22:11:15 +00001059 if (first_param)
1060 first_param = false;
Kate Stonee2b21862014-07-22 17:03:38 +00001061 else WriteCommaSpace();
Jason Molenda026aa492014-10-15 22:11:15 +00001062
1063 if (!ParseType())
1064 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001065 continue;
1066 }
1067 }
1068 break;
1069 }
Jason Molenda026aa492014-10-15 22:11:15 +00001070
Kate Stonee2b21862014-07-22 17:03:38 +00001071 if (qualifiers)
1072 {
Jason Molenda026aa492014-10-15 22:11:15 +00001073 WriteQualifiers (qualifiers);
1074 EndSubstitution (return_type_start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001075 }
Jason Molenda026aa492014-10-15 22:11:15 +00001076
Kate Stonee2b21862014-07-22 17:03:38 +00001077 if (inner_qualifiers)
1078 {
1079 int qualifier_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001080 Write ('(');
1081 WriteQualifiers (inner_qualifiers);
1082 Write (')');
1083 ReorderRange (EndRange (qualifier_start_cookie), insert_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001084 }
1085 return true;
Jason Molenda61e0a3e2014-10-17 01:36:20 +00001086#endif // TODO
Kate Stonee2b21862014-07-22 17:03:38 +00001087 }
Jason Molenda026aa492014-10-15 22:11:15 +00001088
Kate Stonee2b21862014-07-22 17:03:38 +00001089 // <array-type> ::= A <positive dimension number> _ <element type>
1090 // ::= A [<dimension expression>] _ <element type>
Jason Molenda026aa492014-10-15 22:11:15 +00001091
1092 bool
1093 ParseArrayType(int qualifiers = QualifierNone)
Kate Stonee2b21862014-07-22 17:03:38 +00001094 {
1095#ifdef DEBUG_FAILURES
1096 printf("*** Array type unsupported\n");
1097#endif
1098 //TODO: We fail horribly when recalling these as substitutions or
1099 // templates and trying to constify them eg:
1100 // _ZN4llvm2cl5applyIA28_cNS0_3optIbLb0ENS0_6parserIbEEEEEEvRKT_PT0_
1101 //
1102 //TODO: Chances are we don't do any better with references and pointers
1103 // that should be type (&) [] instead of type & []
Jason Molenda026aa492014-10-15 22:11:15 +00001104
Kate Stonee2b21862014-07-22 17:03:38 +00001105 return false;
Jason Molenda026aa492014-10-15 22:11:15 +00001106
Jason Molenda61e0a3e2014-10-17 01:36:20 +00001107#if 0 // TODO
Jason Molenda026aa492014-10-15 22:11:15 +00001108 if (*m_read_ptr == '_')
Kate Stonee2b21862014-07-22 17:03:38 +00001109 {
Jason Molenda026aa492014-10-15 22:11:15 +00001110 ++m_read_ptr;
1111 if (!ParseType())
1112 return false;
1113 if (qualifiers)
1114 WriteQualifiers(qualifiers);
Kate Stonee2b21862014-07-22 17:03:38 +00001115 WRITE(" []");
1116 return true;
1117 }
1118 else
1119 {
Jason Molenda026aa492014-10-15 22:11:15 +00001120 const char *before_digits = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001121 if (TryParseNumber() != -1)
1122 {
Jason Molenda026aa492014-10-15 22:11:15 +00001123 const char *after_digits = m_read_ptr;
1124 if (!Parse('_'))
1125 return false;
1126 if (!ParseType())
1127 return false;
1128 if (qualifiers)
1129 WriteQualifiers(qualifiers);
Kate Stonee2b21862014-07-22 17:03:38 +00001130 Write(' ');
1131 Write('[');
1132 Write(before_digits, after_digits - before_digits);
1133 }
1134 else
1135 {
1136 int type_insertion_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001137 if (!ParseExpression())
1138 return false;
1139 if (!Parse('_'))
1140 return false;
1141
Kate Stonee2b21862014-07-22 17:03:38 +00001142 int type_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001143 if (!ParseType())
1144 return false;
1145 if (qualifiers)
1146 WriteQualifiers(qualifiers);
Kate Stonee2b21862014-07-22 17:03:38 +00001147 Write(' ');
1148 Write('[');
Jason Molenda026aa492014-10-15 22:11:15 +00001149 ReorderRange (EndRange (type_start_cookie), type_insertion_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001150 }
1151 Write(']');
1152 return true;
1153 }
Jason Molenda61e0a3e2014-10-17 01:36:20 +00001154#endif // TODO
Kate Stonee2b21862014-07-22 17:03:38 +00001155 }
Jason Molenda026aa492014-10-15 22:11:15 +00001156
Kate Stonee2b21862014-07-22 17:03:38 +00001157 // <pointer-to-member-type> ::= M <class type> <member type>
Jason Molenda026aa492014-10-15 22:11:15 +00001158
Kate Stonee2b21862014-07-22 17:03:38 +00001159 //TODO: Determine how to handle pointers to function members correctly,
1160 // currently not an issue because we don't have function types at all...
Jason Molenda026aa492014-10-15 22:11:15 +00001161 bool
1162 ParsePointerToMemberType()
Kate Stonee2b21862014-07-22 17:03:38 +00001163 {
1164 int insertion_cookie = GetStartCookie();
1165 Write(' ');
Jason Molenda026aa492014-10-15 22:11:15 +00001166 if (!ParseType())
1167 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001168 WRITE("::*");
Jason Molenda026aa492014-10-15 22:11:15 +00001169
Kate Stonee2b21862014-07-22 17:03:38 +00001170 int type_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001171 if (!ParseType())
1172 return false;
1173 ReorderRange (EndRange (type_cookie), insertion_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001174 return true;
1175 }
Jason Molenda026aa492014-10-15 22:11:15 +00001176
Kate Stonee2b21862014-07-22 17:03:38 +00001177 // <template-param> ::= T_ # first template parameter
1178 // ::= T <parameter-2 non-negative number> _
Jason Molenda026aa492014-10-15 22:11:15 +00001179
1180 bool
1181 ParseTemplateParam()
Kate Stonee2b21862014-07-22 17:03:38 +00001182 {
1183 int count = TryParseNumber();
Jason Molenda026aa492014-10-15 22:11:15 +00001184 if (!Parse('_'))
1185 return false;
1186
Kate Stonee2b21862014-07-22 17:03:38 +00001187 // When no number is present we get -1, which is convenient since
1188 // T_ is the zeroth element T0_ is element 1, and so on
Jason Molenda026aa492014-10-15 22:11:15 +00001189 return RewriteTemplateArg (count + 1);
Kate Stonee2b21862014-07-22 17:03:38 +00001190 }
Jason Molenda026aa492014-10-15 22:11:15 +00001191
Kate Stonee2b21862014-07-22 17:03:38 +00001192 // <type> ::= <builtin-type>
1193 // ::= <function-type>
1194 // ::= <class-enum-type>
1195 // ::= <array-type>
1196 // ::= <pointer-to-member-type>
1197 // ::= <template-param>
1198 // ::= <template-template-param> <template-args>
1199 // ::= <decltype>
1200 // ::= <substitution>
1201 // ::= <CV-qualifiers> <type>
1202 // ::= P <type> # pointer-to
1203 // ::= R <type> # reference-to
1204 // ::= O <type> # rvalue reference-to (C++0x)
1205 // ::= C <type> # complex pair (C 2000)
1206 // ::= G <type> # imaginary (C 2000)
1207 // ::= Dp <type> # pack expansion (C++0x)
1208 // ::= U <source-name> <type> # vendor extended type qualifier
1209 // extension := U <objc-name> <objc-type> # objc-type<identifier>
1210 // extension := <vector-type> # <vector-type> starts with Dv
Jason Molenda026aa492014-10-15 22:11:15 +00001211
Kate Stonee2b21862014-07-22 17:03:38 +00001212 // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
1213 // <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001214
1215 bool
1216 ParseType()
Kate Stonee2b21862014-07-22 17:03:38 +00001217 {
1218#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001219 const char *failed_type = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001220#endif
1221 int type_start_cookie = GetStartCookie();
1222 bool suppress_substitution = false;
Jason Molenda026aa492014-10-15 22:11:15 +00001223
1224 int qualifiers = TryParseQualifiers (true, false);
1225 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00001226 {
1227 case 'D':
Jason Molenda026aa492014-10-15 22:11:15 +00001228 ++m_read_ptr;
1229 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001230 {
1231 case 'p':
Jason Molenda026aa492014-10-15 22:11:15 +00001232 if (!ParseType())
1233 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001234 break;
1235 case 'T':
1236 case 't':
1237 case 'v':
1238 default:
1239#ifdef DEBUG_FAILURES
1240 printf("*** Unsupported type: %.3s\n", failed_type);
1241#endif
1242 return false;
1243 }
1244 break;
1245 case 'T':
Jason Molenda026aa492014-10-15 22:11:15 +00001246 ++m_read_ptr;
1247 if (!ParseTemplateParam())
1248 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001249 break;
1250 case 'M':
Jason Molenda026aa492014-10-15 22:11:15 +00001251 ++m_read_ptr;
1252 if (!ParsePointerToMemberType())
1253 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001254 break;
1255 case 'A':
Jason Molenda026aa492014-10-15 22:11:15 +00001256 ++m_read_ptr;
1257 if (!ParseArrayType())
1258 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001259 break;
1260 case 'F':
Jason Molenda026aa492014-10-15 22:11:15 +00001261 ++m_read_ptr;
1262 if (!ParseFunctionType())
1263 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001264 break;
1265 case 'S':
Jason Molenda026aa492014-10-15 22:11:15 +00001266 if (*++m_read_ptr == 't')
Kate Stonee2b21862014-07-22 17:03:38 +00001267 {
Jason Molenda026aa492014-10-15 22:11:15 +00001268 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001269 WriteStdPrefix();
Jason Molenda026aa492014-10-15 22:11:15 +00001270 if (!ParseName())
1271 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001272 }
1273 else
1274 {
1275 suppress_substitution = true;
Jason Molenda026aa492014-10-15 22:11:15 +00001276 if (!ParseSubstitution())
1277 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001278 }
1279 break;
1280 case 'P':
1281 {
Jason Molenda026aa492014-10-15 22:11:15 +00001282 switch (*++m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00001283 {
1284 case 'F':
Jason Molenda026aa492014-10-15 22:11:15 +00001285 ++m_read_ptr;
1286 if (!ParseFunctionType(QualifierPointer))
1287 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001288 break;
1289 default:
Jason Molenda026aa492014-10-15 22:11:15 +00001290 if (!ParseType())
1291 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001292 Write('*');
1293 break;
1294 }
1295 break;
1296 }
1297 case 'R':
1298 {
Jason Molenda026aa492014-10-15 22:11:15 +00001299 ++m_read_ptr;
1300 if (!ParseType())
1301 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001302 Write('&');
1303 break;
1304 }
1305 case 'O':
1306 {
Jason Molenda026aa492014-10-15 22:11:15 +00001307 ++m_read_ptr;
1308 if (!ParseType())
1309 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001310 Write('&');
1311 Write('&');
1312 break;
1313 }
1314 case 'C':
1315 case 'G':
1316 case 'U':
1317#ifdef DEBUG_FAILURES
1318 printf("*** Unsupported type: %.3s\n", failed_type);
1319#endif
1320 return false;
1321 // Test for common cases to avoid TryParseBuiltinType() overhead
1322 case 'N':
1323 case 'Z':
1324 case 'L':
Jason Molenda026aa492014-10-15 22:11:15 +00001325 if (!ParseName())
1326 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001327 break;
1328 default:
Jason Molenda026aa492014-10-15 22:11:15 +00001329 if (const char *builtin = TryParseBuiltinType())
Kate Stonee2b21862014-07-22 17:03:38 +00001330 {
1331 Write(builtin);
1332 suppress_substitution = true;
1333 }
1334 else
1335 {
Jason Molenda026aa492014-10-15 22:11:15 +00001336 if (!ParseName())
1337 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001338 }
1339 break;
1340 }
Jason Molenda026aa492014-10-15 22:11:15 +00001341
Kate Stonee2b21862014-07-22 17:03:38 +00001342 // Allow base substitutions to be suppressed, but always record
1343 // substitutions for the qualified variant
Jason Molenda026aa492014-10-15 22:11:15 +00001344 if (!suppress_substitution)
1345 EndSubstitution(type_start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001346 if (qualifiers)
1347 {
1348 WriteQualifiers(qualifiers, false);
1349 EndSubstitution(type_start_cookie);
1350 }
1351 return true;
1352 }
Jason Molenda026aa492014-10-15 22:11:15 +00001353
Kate Stonee2b21862014-07-22 17:03:38 +00001354 // <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
1355 // ::= <closure-type-name>
1356 //
1357 // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
1358 //
1359 // <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Jason Molenda026aa492014-10-15 22:11:15 +00001360
1361 bool
1362 ParseUnnamedTypeName(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001363 {
Jason Molenda026aa492014-10-15 22:11:15 +00001364 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001365 {
1366 case 't':
1367 {
1368 int cookie = GetStartCookie();
1369 WRITE("'unnamed");
Jason Molenda026aa492014-10-15 22:11:15 +00001370 const char *before_digits = m_read_ptr;
1371 if (TryParseNumber() != -1) Write (before_digits,
1372 m_read_ptr - before_digits);
1373 if (!Parse('_'))
1374 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001375 Write('\'');
Jason Molenda026aa492014-10-15 22:11:15 +00001376 name_state.last_name_range = EndRange (cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001377 return true;
1378 }
1379 case 'b':
1380 {
1381 int cookie = GetStartCookie();
1382 WRITE("'block");
Jason Molenda026aa492014-10-15 22:11:15 +00001383 const char *before_digits = m_read_ptr;
1384 if (TryParseNumber() != -1) Write (before_digits,
1385 m_read_ptr - before_digits);
1386 if (!Parse('_'))
1387 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001388 Write('\'');
Jason Molenda026aa492014-10-15 22:11:15 +00001389 name_state.last_name_range = EndRange (cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001390 return true;
1391 }
1392 case 'l':
1393#ifdef DEBUG_FAILURES
1394 printf("*** Lambda type names unsupported\n");
1395#endif
1396 return false;
1397 }
1398#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001399 printf("*** Unknown unnamed type %.3s\n", m_read_ptr - 2);
Kate Stonee2b21862014-07-22 17:03:38 +00001400#endif
1401 return false;
1402 }
Jason Molenda026aa492014-10-15 22:11:15 +00001403
Kate Stonee2b21862014-07-22 17:03:38 +00001404 // <ctor-dtor-name> ::= C1 # complete object constructor
1405 // ::= C2 # base object constructor
1406 // ::= C3 # complete object allocating constructor
Jason Molenda026aa492014-10-15 22:11:15 +00001407
1408 bool
1409 ParseCtor(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001410 {
Jason Molenda026aa492014-10-15 22:11:15 +00001411 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001412 if (next == '1' || next == '2' || next == '3' || next == '5')
1413 {
Jason Molenda026aa492014-10-15 22:11:15 +00001414 RewriteRange (name_state.last_name_range);
Kate Stonee2b21862014-07-22 17:03:38 +00001415 name_state.has_no_return_type = true;
Jason Molenda026aa492014-10-15 22:11:15 +00001416 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001417 return true;
1418 }
1419#ifdef DEBUG_FAILURES
1420 printf("*** Broken constructor\n");
1421#endif
1422 return false;
1423 }
Jason Molenda026aa492014-10-15 22:11:15 +00001424
Kate Stonee2b21862014-07-22 17:03:38 +00001425 // <ctor-dtor-name> ::= D0 # deleting destructor
1426 // ::= D1 # complete object destructor
1427 // ::= D2 # base object destructor
Jason Molenda026aa492014-10-15 22:11:15 +00001428
1429 bool
1430 ParseDtor(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001431 {
Jason Molenda026aa492014-10-15 22:11:15 +00001432 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001433 if (next == '0' || next == '1' || next == '2' || next == '5')
1434 {
1435 Write('~');
1436 RewriteRange(name_state.last_name_range);
1437 name_state.has_no_return_type = true;
Jason Molenda026aa492014-10-15 22:11:15 +00001438 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001439 return true;
1440 }
1441#ifdef DEBUG_FAILURES
1442 printf("*** Broken destructor\n");
1443#endif
1444 return false;
1445 }
Jason Molenda026aa492014-10-15 22:11:15 +00001446
Kate Stonee2b21862014-07-22 17:03:38 +00001447 // See TryParseOperator()
Jason Molenda026aa492014-10-15 22:11:15 +00001448
1449 bool
1450 ParseOperatorName(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001451 {
1452#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001453 const char *operator_ptr = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001454#endif
1455 Operator parsed_operator = TryParseOperator();
1456 if (parsed_operator.name)
1457 {
1458 WRITE("operator");
1459 Write(parsed_operator.name);
1460 return true;
1461 }
Jason Molenda026aa492014-10-15 22:11:15 +00001462
Kate Stonee2b21862014-07-22 17:03:38 +00001463 // Handle special operators
1464 switch (parsed_operator.kind)
1465 {
1466 case OperatorKind::Vendor:
1467 WRITE("operator ");
1468 return ParseSourceName();
1469 case OperatorKind::ConversionOperator:
1470 ResetTemplateArgs();
1471 name_state.has_no_return_type = true;
1472 WRITE("operator ");
1473 return ParseType();
1474 default:
1475#ifdef DEBUG_FAILURES
1476 printf("*** Unknown operator: %.2s\n", operator_ptr);
1477#endif
1478 return false;
1479 }
1480 }
Jason Molenda026aa492014-10-15 22:11:15 +00001481
Kate Stonee2b21862014-07-22 17:03:38 +00001482 // <source-name> ::= <positive length number> <identifier>
Jason Molenda026aa492014-10-15 22:11:15 +00001483
1484 bool
1485 ParseSourceName()
Kate Stonee2b21862014-07-22 17:03:38 +00001486 {
1487 int count = TryParseNumber();
1488 if (count == -1)
1489 {
1490#ifdef DEBUG_FAILURES
1491 printf("*** Malformed source name, missing length count\n");
1492#endif
1493 return false;
1494 }
Jason Molenda026aa492014-10-15 22:11:15 +00001495
1496 const char *next_m_read_ptr = m_read_ptr + count;
1497 if (next_m_read_ptr > m_read_end)
Kate Stonee2b21862014-07-22 17:03:38 +00001498 {
1499#ifdef DEBUG_FAILURES
1500 printf("*** Malformed source name, premature termination\n");
1501#endif
1502 return false;
1503 }
Jason Molenda026aa492014-10-15 22:11:15 +00001504
1505 if (count >= 10 && strncmp(m_read_ptr, "_GLOBAL__N", 10) == 0)
1506 WRITE("(anonymous namespace)");
1507 else Write(m_read_ptr, count);
1508
1509 m_read_ptr = next_m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001510 return true;
1511 }
Jason Molenda026aa492014-10-15 22:11:15 +00001512
Kate Stonee2b21862014-07-22 17:03:38 +00001513 // <unqualified-name> ::= <operator-name>
1514 // ::= <ctor-dtor-name>
1515 // ::= <source-name>
1516 // ::= <unnamed-type-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001517
1518 bool
1519 ParseUnqualifiedName(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001520 {
1521 // Note that these are detected directly in ParseNestedName for
1522 // performance rather than switching on the same options twice
Jason Molenda026aa492014-10-15 22:11:15 +00001523 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001524 switch (next)
1525 {
1526 case 'C':
Jason Molenda026aa492014-10-15 22:11:15 +00001527 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001528 return ParseCtor(name_state);
1529 case 'D':
Jason Molenda026aa492014-10-15 22:11:15 +00001530 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001531 return ParseDtor(name_state);
1532 case 'U':
Jason Molenda026aa492014-10-15 22:11:15 +00001533 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001534 return ParseUnnamedTypeName(name_state);
1535 case '0':
1536 case '1':
1537 case '2':
1538 case '3':
1539 case '4':
1540 case '5':
1541 case '6':
1542 case '7':
1543 case '8':
1544 case '9':
1545 {
1546 int name_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001547 if (!ParseSourceName())
1548 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001549 name_state.last_name_range = EndRange(name_start_cookie);
1550 return true;
1551 }
1552 default:
1553 return ParseOperatorName(name_state);
1554 };
1555 }
Jason Molenda026aa492014-10-15 22:11:15 +00001556
Kate Stonee2b21862014-07-22 17:03:38 +00001557 // <unscoped-name> ::= <unqualified-name>
1558 // ::= St <unqualified-name> # ::std::
1559 // extension ::= StL<unqualified-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001560
1561 bool
1562 ParseUnscopedName(NameState & name_state)
Kate Stonee2b21862014-07-22 17:03:38 +00001563 {
Jason Molenda026aa492014-10-15 22:11:15 +00001564 if (*m_read_ptr == 'S' && *(m_read_ptr + 1) == 't')
Kate Stonee2b21862014-07-22 17:03:38 +00001565 {
1566 WriteStdPrefix();
Jason Molenda026aa492014-10-15 22:11:15 +00001567 if (*(m_read_ptr += 2) == 'L')
1568 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001569 }
1570 return ParseUnqualifiedName(name_state);
1571 }
Jason Molenda026aa492014-10-15 22:11:15 +00001572
1573 bool
1574 ParseIntegerLiteral(const char *prefix, const char *suffix,
Kate Stonee2b21862014-07-22 17:03:38 +00001575 bool allow_negative)
1576 {
Jason Molenda026aa492014-10-15 22:11:15 +00001577 if (prefix)
1578 Write(prefix);
1579 if (!ParseNumber(allow_negative))
1580 return false;
1581 if (suffix)
1582 Write(suffix);
Kate Stonee2b21862014-07-22 17:03:38 +00001583 return Parse('E');
1584 }
Jason Molenda026aa492014-10-15 22:11:15 +00001585
1586 bool
1587 ParseBooleanLiteral()
Kate Stonee2b21862014-07-22 17:03:38 +00001588 {
Jason Molenda026aa492014-10-15 22:11:15 +00001589 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001590 {
1591 case '0': WRITE("false"); break;
1592 case '1': WRITE("true"); break;
1593 default:
1594#ifdef DEBUG_FAILURES
1595 printf("*** Boolean literal not 0 or 1\n");
1596#endif
1597 return false;
1598 }
1599 return Parse('E');
1600 }
Jason Molenda026aa492014-10-15 22:11:15 +00001601
Kate Stonee2b21862014-07-22 17:03:38 +00001602 // <expr-primary> ::= L <type> <value number> E # integer literal
1603 // ::= L <type> <value float> E # floating literal
1604 // ::= L <string type> E # string literal
1605 // ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
1606 // ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
1607 // ::= L <mangled-name> E # external name
Jason Molenda026aa492014-10-15 22:11:15 +00001608
1609 bool
1610 ParseExpressionPrimary()
Kate Stonee2b21862014-07-22 17:03:38 +00001611 {
Jason Molenda026aa492014-10-15 22:11:15 +00001612 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001613 {
1614 case 'b': return ParseBooleanLiteral();
1615 case 'x': return ParseIntegerLiteral(nullptr, "ll", true);
1616 case 'l': return ParseIntegerLiteral(nullptr, "l", true);
1617 case 'i': return ParseIntegerLiteral(nullptr, nullptr, true);
1618 case 'n': return ParseIntegerLiteral("(__int128)", nullptr, true);
1619 case 'j': return ParseIntegerLiteral(nullptr, "u", false);
1620 case 'm': return ParseIntegerLiteral(nullptr, "ul", false);
1621 case 'y': return ParseIntegerLiteral(nullptr, "ull", false);
1622 case 'o': return ParseIntegerLiteral("(unsigned __int128)",
1623 nullptr, false);
1624 case '_':
Jason Molenda026aa492014-10-15 22:11:15 +00001625 if (*m_read_ptr++ == 'Z')
Kate Stonee2b21862014-07-22 17:03:38 +00001626 {
Jason Molenda026aa492014-10-15 22:11:15 +00001627 if (!ParseEncoding())
1628 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001629 return Parse('E');
1630 }
Jason Molenda026aa492014-10-15 22:11:15 +00001631 --m_read_ptr;
Jason Molenda62e06812016-02-16 04:14:33 +00001632 LLVM_FALLTHROUGH;
Kate Stonee2b21862014-07-22 17:03:38 +00001633 case 'w':
1634 case 'c':
1635 case 'a':
1636 case 'h':
1637 case 's':
1638 case 't':
1639 case 'f':
1640 case 'd':
1641 case 'e':
1642#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001643 printf("*** Unsupported primary expression %.5s\n", m_read_ptr - 1);
Kate Stonee2b21862014-07-22 17:03:38 +00001644#endif
1645 return false;
1646 case 'T':
1647 // Invalid mangled name per
1648 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
1649#ifdef DEBUG_FAILURES
1650 printf("*** Invalid primary expr encoding\n");
1651#endif
1652 return false;
1653 default:
Jason Molenda026aa492014-10-15 22:11:15 +00001654 --m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001655 Write('(');
Jason Molenda026aa492014-10-15 22:11:15 +00001656 if (!ParseType())
1657 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001658 Write(')');
Jason Molenda026aa492014-10-15 22:11:15 +00001659 if (!ParseNumber())
1660 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001661 return Parse('E');
1662 }
1663 }
Jason Molenda026aa492014-10-15 22:11:15 +00001664
Kate Stonee2b21862014-07-22 17:03:38 +00001665 // <unresolved-type> ::= <template-param>
1666 // ::= <decltype>
1667 // ::= <substitution>
Jason Molenda026aa492014-10-15 22:11:15 +00001668
1669 bool
1670 ParseUnresolvedType()
Kate Stonee2b21862014-07-22 17:03:38 +00001671 {
1672 int type_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001673 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001674 {
1675 case 'T':
Jason Molenda026aa492014-10-15 22:11:15 +00001676 if (!ParseTemplateParam())
1677 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001678 EndSubstitution(type_start_cookie);
1679 return true;
1680 case 'S':
1681 {
Jason Molenda026aa492014-10-15 22:11:15 +00001682 if (*m_read_ptr != 't')
1683 return ParseSubstitution();
1684
1685 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001686 WriteStdPrefix();
1687 NameState type_name = {};
Jason Molenda026aa492014-10-15 22:11:15 +00001688 if (!ParseUnqualifiedName(type_name))
1689 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001690 EndSubstitution(type_start_cookie);
1691 return true;
Jason Molenda026aa492014-10-15 22:11:15 +00001692
Kate Stonee2b21862014-07-22 17:03:38 +00001693 }
1694 case 'D':
1695 default:
1696#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00001697 printf("*** Unsupported unqualified type: %3s\n", m_read_ptr - 1);
Kate Stonee2b21862014-07-22 17:03:38 +00001698#endif
1699 return false;
1700 }
1701 }
Jason Molenda026aa492014-10-15 22:11:15 +00001702
Kate Stonee2b21862014-07-22 17:03:38 +00001703 // <base-unresolved-name> ::= <simple-id> # unresolved name
1704 // extension ::= <operator-name> # unresolved operator-function-id
1705 // extension ::= <operator-name> <template-args> # unresolved operator template-id
1706 // ::= on <operator-name> # unresolved operator-function-id
1707 // ::= on <operator-name> <template-args> # unresolved operator template-id
1708 // ::= dn <destructor-name> # destructor or pseudo-destructor;
1709 // # e.g. ~X or ~X<N-1>
Jason Molenda026aa492014-10-15 22:11:15 +00001710
1711 bool
1712 ParseBaseUnresolvedName()
Kate Stonee2b21862014-07-22 17:03:38 +00001713 {
1714#ifdef DEBUG_FAILURES
1715 printf("*** Base unresolved name unsupported\n");
1716#endif
1717 return false;
1718 }
Jason Molenda026aa492014-10-15 22:11:15 +00001719
Kate Stonee2b21862014-07-22 17:03:38 +00001720 // <unresolved-name>
1721 // extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
1722 // ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
1723 // ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
1724 // # A::x, N::y, A<T>::z; "gs" means leading "::"
1725 // ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
1726 // extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
1727 // # T::N::x /decltype(p)::N::x
1728 // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001729
1730 bool
1731 ParseUnresolvedName()
Kate Stonee2b21862014-07-22 17:03:38 +00001732 {
1733#ifdef DEBUG_FAILURES
1734 printf("*** Unresolved names not supported\n");
1735#endif
1736 //TODO: grammar for all of this seems unclear...
1737 return false;
Jason Molenda026aa492014-10-15 22:11:15 +00001738
Jason Molenda61e0a3e2014-10-17 01:36:20 +00001739#if 0 // TODO
Jason Molenda026aa492014-10-15 22:11:15 +00001740 if (*m_read_ptr == 'g' && *(m_read_ptr + 1) == 's')
Kate Stonee2b21862014-07-22 17:03:38 +00001741 {
Jason Molenda026aa492014-10-15 22:11:15 +00001742 m_read_ptr += 2;
Kate Stonee2b21862014-07-22 17:03:38 +00001743 WriteNamespaceSeparator();
1744 }
Jason Molenda61e0a3e2014-10-17 01:36:20 +00001745#endif // TODO
Kate Stonee2b21862014-07-22 17:03:38 +00001746 }
Jason Molenda026aa492014-10-15 22:11:15 +00001747
Kate Stonee2b21862014-07-22 17:03:38 +00001748 // <expression> ::= <unary operator-name> <expression>
1749 // ::= <binary operator-name> <expression> <expression>
1750 // ::= <ternary operator-name> <expression> <expression> <expression>
1751 // ::= cl <expression>+ E # call
1752 // ::= cv <type> <expression> # conversion with one argument
1753 // ::= cv <type> _ <expression>* E # conversion with a different number of arguments
1754 // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
1755 // ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
1756 // ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
1757 // ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1758 // ::= [gs] dl <expression> # delete expression
1759 // ::= [gs] da <expression> # delete[] expression
1760 // ::= pp_ <expression> # prefix ++
1761 // ::= mm_ <expression> # prefix --
1762 // ::= ti <type> # typeid (type)
1763 // ::= te <expression> # typeid (expression)
1764 // ::= dc <type> <expression> # dynamic_cast<type> (expression)
1765 // ::= sc <type> <expression> # static_cast<type> (expression)
1766 // ::= cc <type> <expression> # const_cast<type> (expression)
1767 // ::= rc <type> <expression> # reinterpret_cast<type> (expression)
1768 // ::= st <type> # sizeof (a type)
1769 // ::= sz <expression> # sizeof (an expression)
1770 // ::= at <type> # alignof (a type)
1771 // ::= az <expression> # alignof (an expression)
1772 // ::= nx <expression> # noexcept (expression)
1773 // ::= <template-param>
1774 // ::= <function-param>
1775 // ::= dt <expression> <unresolved-name> # expr.name
1776 // ::= pt <expression> <unresolved-name> # expr->name
1777 // ::= ds <expression> <expression> # expr.*expr
1778 // ::= sZ <template-param> # size of a parameter pack
1779 // ::= sZ <function-param> # size of a function parameter pack
1780 // ::= sp <expression> # pack expansion
1781 // ::= tw <expression> # throw expression
1782 // ::= tr # throw with no operand (rethrow)
1783 // ::= <unresolved-name> # f(p), N::f(p), ::f(p),
1784 // # freestanding dependent name (e.g., T::x),
1785 // # objectless nonstatic member reference
1786 // ::= <expr-primary>
Jason Molenda026aa492014-10-15 22:11:15 +00001787
1788 bool
1789 ParseExpression()
Kate Stonee2b21862014-07-22 17:03:38 +00001790 {
1791 Operator expression_operator = TryParseOperator();
1792 switch (expression_operator.kind)
1793 {
1794 case OperatorKind::Unary:
1795 Write(expression_operator.name);
1796 Write('(');
Jason Molenda026aa492014-10-15 22:11:15 +00001797 if (!ParseExpression())
1798 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001799 Write(')');
1800 return true;
1801 case OperatorKind::Binary:
Jason Molenda026aa492014-10-15 22:11:15 +00001802 if (!ParseExpression())
1803 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001804 Write(expression_operator.name);
1805 return ParseExpression();
1806 case OperatorKind::Ternary:
Jason Molenda026aa492014-10-15 22:11:15 +00001807 if (!ParseExpression())
1808 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001809 Write('?');
Jason Molenda026aa492014-10-15 22:11:15 +00001810 if (!ParseExpression())
1811 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001812 Write(':');
1813 return ParseExpression();
1814 case OperatorKind::NoMatch:
1815 break;
1816 case OperatorKind::Other:
1817 default:
1818#ifdef DEBUG_FAILURES
1819 printf("*** Unsupported operator: %s\n", expression_operator.name);
1820#endif
1821 return false;
1822 }
Jason Molenda026aa492014-10-15 22:11:15 +00001823
1824 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00001825 {
1826 case 'T': return ParseTemplateParam();
1827 case 'L': return ParseExpressionPrimary();
1828 case 's':
Jason Molenda026aa492014-10-15 22:11:15 +00001829 if (*m_read_ptr++ == 'r')
1830 return ParseUnresolvedName();
1831 --m_read_ptr;
Jason Molenda62e06812016-02-16 04:14:33 +00001832 LLVM_FALLTHROUGH;
Kate Stonee2b21862014-07-22 17:03:38 +00001833 default:
1834 return ParseExpressionPrimary();
1835 }
1836 }
Jason Molenda026aa492014-10-15 22:11:15 +00001837
Kate Stonee2b21862014-07-22 17:03:38 +00001838 // <template-arg> ::= <type> # type or template
1839 // ::= X <expression> E # expression
1840 // ::= <expr-primary> # simple expressions
1841 // ::= J <template-arg>* E # argument pack
1842 // ::= LZ <encoding> E # extension
Jason Molenda026aa492014-10-15 22:11:15 +00001843
1844 bool
1845 ParseTemplateArg()
Kate Stonee2b21862014-07-22 17:03:38 +00001846 {
Jason Molenda026aa492014-10-15 22:11:15 +00001847 switch (*m_read_ptr) {
Kate Stonee2b21862014-07-22 17:03:38 +00001848 case 'J':
1849#ifdef DEBUG_FAILURES
1850 printf("*** Template argument packs unsupported\n");
1851#endif
1852 return false;
1853 case 'X':
Jason Molenda026aa492014-10-15 22:11:15 +00001854 ++m_read_ptr;
1855 if (!ParseExpression())
1856 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001857 return Parse('E');
1858 case 'L':
Jason Molenda026aa492014-10-15 22:11:15 +00001859 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001860 return ParseExpressionPrimary();
1861 default:
1862 return ParseType();
1863 }
1864 }
Jason Molenda026aa492014-10-15 22:11:15 +00001865
Kate Stonee2b21862014-07-22 17:03:38 +00001866 // <template-args> ::= I <template-arg>* E
1867 // extension, the abi says <template-arg>+
Jason Molenda026aa492014-10-15 22:11:15 +00001868
1869 bool
1870 ParseTemplateArgs(bool record_template_args = false)
Kate Stonee2b21862014-07-22 17:03:38 +00001871 {
Jason Molenda026aa492014-10-15 22:11:15 +00001872 if (record_template_args)
1873 ResetTemplateArgs();
1874
Kate Stonee2b21862014-07-22 17:03:38 +00001875 bool first_arg = true;
Jason Molenda026aa492014-10-15 22:11:15 +00001876 while (*m_read_ptr != 'E')
Kate Stonee2b21862014-07-22 17:03:38 +00001877 {
Jason Molenda026aa492014-10-15 22:11:15 +00001878 if (first_arg)
1879 first_arg = false;
Kate Stonee2b21862014-07-22 17:03:38 +00001880 else WriteCommaSpace();
Jason Molenda026aa492014-10-15 22:11:15 +00001881
Kate Stonee2b21862014-07-22 17:03:38 +00001882 int template_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001883 if (!ParseTemplateArg())
1884 return false;
1885 if (record_template_args)
1886 EndTemplateArg(template_start_cookie);
Kate Stonee2b21862014-07-22 17:03:38 +00001887 }
Jason Molenda026aa492014-10-15 22:11:15 +00001888 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001889 return true;
1890 }
Jason Molenda026aa492014-10-15 22:11:15 +00001891
Kate Stonee2b21862014-07-22 17:03:38 +00001892 // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
1893 // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
1894 //
1895 // <prefix> ::= <prefix> <unqualified-name>
1896 // ::= <template-prefix> <template-args>
1897 // ::= <template-param>
1898 // ::= <decltype>
1899 // ::= # empty
1900 // ::= <substitution>
1901 // ::= <prefix> <data-member-prefix>
1902 // extension ::= L
1903 //
1904 // <template-prefix> ::= <prefix> <template unqualified-name>
1905 // ::= <template-param>
1906 // ::= <substitution>
1907 //
1908 // <unqualified-name> ::= <operator-name>
1909 // ::= <ctor-dtor-name>
1910 // ::= <source-name>
1911 // ::= <unnamed-type-name>
Jason Molenda026aa492014-10-15 22:11:15 +00001912
1913 bool
1914 ParseNestedName(NameState & name_state, bool parse_discriminator = false)
Kate Stonee2b21862014-07-22 17:03:38 +00001915 {
1916 int qualifiers = TryParseQualifiers(true, true);
1917 bool first_part = true;
1918 bool suppress_substitution = true;
1919 int name_start_cookie = GetStartCookie();
1920 while (true)
1921 {
Jason Molenda026aa492014-10-15 22:11:15 +00001922 char next = *m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001923 if (next == 'E')
1924 {
Jason Molenda026aa492014-10-15 22:11:15 +00001925 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001926 break;
1927 }
Jason Molenda026aa492014-10-15 22:11:15 +00001928
Kate Stonee2b21862014-07-22 17:03:38 +00001929 // Record a substitution candidate for all prefixes, but not the full name
Jason Molenda026aa492014-10-15 22:11:15 +00001930 if (suppress_substitution)
1931 suppress_substitution = false;
Kate Stonee2b21862014-07-22 17:03:38 +00001932 else EndSubstitution(name_start_cookie);
Jason Molenda026aa492014-10-15 22:11:15 +00001933
Kate Stonee2b21862014-07-22 17:03:38 +00001934 if (next == 'I')
1935 {
Jason Molenda026aa492014-10-15 22:11:15 +00001936 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00001937 name_state.is_last_generic = true;
1938 WriteTemplateStart();
Jason Molenda026aa492014-10-15 22:11:15 +00001939 if (!ParseTemplateArgs(name_state.parse_function_params))
1940 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001941 WriteTemplateEnd();
1942 continue;
1943 }
Jason Molenda026aa492014-10-15 22:11:15 +00001944
1945 if (first_part)
1946 first_part = false;
Kate Stonee2b21862014-07-22 17:03:38 +00001947 else WriteNamespaceSeparator();
Jason Molenda026aa492014-10-15 22:11:15 +00001948
Kate Stonee2b21862014-07-22 17:03:38 +00001949 name_state.is_last_generic = false;
1950 switch (next)
1951 {
1952 case '0':
1953 case '1':
1954 case '2':
1955 case '3':
1956 case '4':
1957 case '5':
1958 case '6':
1959 case '7':
1960 case '8':
1961 case '9':
1962 {
1963 int name_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00001964 if (!ParseSourceName())
1965 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001966 name_state.last_name_range = EndRange(name_start_cookie);
1967 continue;
1968 }
1969 case 'S':
Jason Molenda026aa492014-10-15 22:11:15 +00001970 if (*++m_read_ptr == 't')
Kate Stonee2b21862014-07-22 17:03:38 +00001971 {
1972 WriteStdPrefix();
Jason Molenda026aa492014-10-15 22:11:15 +00001973 ++m_read_ptr;
1974 if (!ParseUnqualifiedName(name_state))
1975 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001976 }
1977 else
1978 {
Jason Molenda026aa492014-10-15 22:11:15 +00001979 if (!ParseSubstitution())
1980 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001981 suppress_substitution = true;
1982 }
1983 continue;
1984 case 'T':
Jason Molenda026aa492014-10-15 22:11:15 +00001985 ++m_read_ptr;
1986 if (!ParseTemplateParam())
1987 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001988 continue;
1989 case 'C':
Jason Molenda026aa492014-10-15 22:11:15 +00001990 ++m_read_ptr;
1991 if (!ParseCtor(name_state))
1992 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00001993 continue;
1994 case 'D':
1995 {
Jason Molenda026aa492014-10-15 22:11:15 +00001996 switch (*(m_read_ptr + 1))
Kate Stonee2b21862014-07-22 17:03:38 +00001997 {
1998 case 't':
1999 case 'T':
2000#ifdef DEBUG_FAILURES
2001 printf("*** Decltype unsupported\n");
2002#endif
2003 return false;
2004 }
Jason Molenda026aa492014-10-15 22:11:15 +00002005 ++m_read_ptr;
2006 if (!ParseDtor(name_state))
2007 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002008 continue;
2009 }
2010 case 'U':
Jason Molenda026aa492014-10-15 22:11:15 +00002011 ++m_read_ptr;
2012 if (!ParseUnnamedTypeName(name_state))
2013 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002014 continue;
2015 case 'L':
Jason Molenda026aa492014-10-15 22:11:15 +00002016 ++m_read_ptr;
2017 if (!ParseUnqualifiedName(name_state))
2018 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002019 continue;
2020 default:
Jason Molenda026aa492014-10-15 22:11:15 +00002021 if (!ParseOperatorName(name_state))
2022 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002023 }
2024 }
Jason Molenda026aa492014-10-15 22:11:15 +00002025
2026 if (parse_discriminator)
2027 TryParseDiscriminator();
2028 if (name_state.parse_function_params
2029 && !ParseFunctionArgs(name_state, name_start_cookie))
2030 {
2031 return false;
2032 }
2033 if (qualifiers)
2034 WriteQualifiers(qualifiers);
Kate Stonee2b21862014-07-22 17:03:38 +00002035 return true;
2036 }
Jason Molenda026aa492014-10-15 22:11:15 +00002037
Kate Stonee2b21862014-07-22 17:03:38 +00002038 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2039 // := Z <function encoding> E s [<discriminator>]
2040 // := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Jason Molenda026aa492014-10-15 22:11:15 +00002041
2042 bool
2043 ParseLocalName(bool parse_function_params)
Kate Stonee2b21862014-07-22 17:03:38 +00002044 {
Jason Molenda026aa492014-10-15 22:11:15 +00002045 if (!ParseEncoding())
2046 return false;
2047 if (!Parse('E'))
2048 return false;
2049
2050 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002051 {
2052 case 's':
Kate Stone641e9f82014-12-06 01:42:41 +00002053 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002054 TryParseDiscriminator(); // Optional and ignored
2055 WRITE("::string literal");
2056 break;
2057 case 'd':
Kate Stone641e9f82014-12-06 01:42:41 +00002058 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002059 TryParseNumber(); // Optional and ignored
Kate Stone641e9f82014-12-06 01:42:41 +00002060 if (!Parse('_'))
2061 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002062 WriteNamespaceSeparator();
Jason Molenda026aa492014-10-15 22:11:15 +00002063 if (!ParseName())
2064 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002065 break;
2066 default:
2067 WriteNamespaceSeparator();
Jason Molenda026aa492014-10-15 22:11:15 +00002068 if (!ParseName(parse_function_params, true))
2069 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002070 TryParseDiscriminator(); // Optional and ignored
2071 }
2072 return true;
2073 }
Jason Molenda026aa492014-10-15 22:11:15 +00002074
Kate Stonee2b21862014-07-22 17:03:38 +00002075 // <name> ::= <nested-name>
2076 // ::= <local-name>
2077 // ::= <unscoped-template-name> <template-args>
2078 // ::= <unscoped-name>
Jason Molenda026aa492014-10-15 22:11:15 +00002079
Kate Stonee2b21862014-07-22 17:03:38 +00002080 // <unscoped-template-name> ::= <unscoped-name>
2081 // ::= <substitution>
Jason Molenda026aa492014-10-15 22:11:15 +00002082
2083 bool
2084 ParseName(bool parse_function_params = false,
Kate Stonee2b21862014-07-22 17:03:38 +00002085 bool parse_discriminator = false)
2086 {
Jason Molenda61e0a3e2014-10-17 01:36:20 +00002087 NameState name_state = { parse_function_params, false, false, {0, 0}};
Kate Stonee2b21862014-07-22 17:03:38 +00002088 int name_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00002089
2090 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002091 {
2092 case 'N':
Jason Molenda026aa492014-10-15 22:11:15 +00002093 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002094 return ParseNestedName(name_state, parse_discriminator);
2095 case 'Z':
2096 {
Jason Molenda026aa492014-10-15 22:11:15 +00002097 ++m_read_ptr;
2098 if (!ParseLocalName(parse_function_params))
2099 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002100 break;
2101 }
2102 case 'L':
Jason Molenda026aa492014-10-15 22:11:15 +00002103 ++m_read_ptr;
Jason Molenda62e06812016-02-16 04:14:33 +00002104 LLVM_FALLTHROUGH;
Kate Stonee2b21862014-07-22 17:03:38 +00002105 default:
2106 {
Jason Molenda026aa492014-10-15 22:11:15 +00002107 if (!ParseUnscopedName(name_state))
2108 return false;
2109
2110 if (*m_read_ptr == 'I')
Kate Stonee2b21862014-07-22 17:03:38 +00002111 {
2112 EndSubstitution(name_start_cookie);
Jason Molenda026aa492014-10-15 22:11:15 +00002113
2114 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002115 name_state.is_last_generic = true;
2116 WriteTemplateStart();
Jason Molenda026aa492014-10-15 22:11:15 +00002117 if (!ParseTemplateArgs(parse_function_params))
2118 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002119 WriteTemplateEnd();
2120 }
2121 break;
2122 }
2123 }
Jason Molenda026aa492014-10-15 22:11:15 +00002124 if (parse_discriminator)
2125 TryParseDiscriminator();
Kate Stonee2b21862014-07-22 17:03:38 +00002126 if (parse_function_params &&
Jason Molenda026aa492014-10-15 22:11:15 +00002127 !ParseFunctionArgs(name_state, name_start_cookie))
2128 {
2129 return false;
2130 }
Kate Stonee2b21862014-07-22 17:03:38 +00002131 return true;
2132 }
Jason Molenda026aa492014-10-15 22:11:15 +00002133
Kate Stonee2b21862014-07-22 17:03:38 +00002134 // <call-offset> ::= h <nv-offset> _
2135 // ::= v <v-offset> _
2136 //
2137 // <nv-offset> ::= <offset number>
2138 // # non-virtual base override
2139 //
2140 // <v-offset> ::= <offset number> _ <virtual offset number>
2141 // # virtual base override, with vcall offset
Jason Molenda026aa492014-10-15 22:11:15 +00002142
2143 bool
2144 ParseCallOffset()
Kate Stonee2b21862014-07-22 17:03:38 +00002145 {
Jason Molenda026aa492014-10-15 22:11:15 +00002146 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00002147 {
2148 case 'h':
Jason Molenda026aa492014-10-15 22:11:15 +00002149 if (*m_read_ptr == 'n')
2150 ++m_read_ptr;
2151 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2152 break;
Kate Stonee2b21862014-07-22 17:03:38 +00002153 return true;
2154 case 'v':
Jason Molenda026aa492014-10-15 22:11:15 +00002155 if (*m_read_ptr == 'n')
2156 ++m_read_ptr;
2157 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2158 break;
2159 if (*m_read_ptr == 'n')
2160 ++m_read_ptr;
2161 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2162 break;
Kate Stonee2b21862014-07-22 17:03:38 +00002163 return true;
2164 }
2165#ifdef DEBUG_FAILURES
2166 printf("*** Malformed call offset\n");
2167#endif
2168 return false;
2169 }
Jason Molenda026aa492014-10-15 22:11:15 +00002170
Kate Stonee2b21862014-07-22 17:03:38 +00002171 // <special-name> ::= TV <type> # virtual table
2172 // ::= TT <type> # VTT structure (construction vtable index)
2173 // ::= TI <type> # typeinfo structure
2174 // ::= TS <type> # typeinfo name (null-terminated byte string)
2175 // ::= Tc <call-offset> <call-offset> <base encoding>
2176 // # base is the nominal target function of thunk
2177 // # first call-offset is 'this' adjustment
2178 // # second call-offset is result adjustment
2179 // ::= T <call-offset> <base encoding>
2180 // # base is the nominal target function of thunk
2181 // extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
Jason Molenda026aa492014-10-15 22:11:15 +00002182
2183 bool
2184 ParseSpecialNameT()
Kate Stonee2b21862014-07-22 17:03:38 +00002185 {
Jason Molenda026aa492014-10-15 22:11:15 +00002186 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00002187 {
2188 case 'V':
2189 WRITE("vtable for ");
2190 return ParseType();
2191 case 'T':
2192 WRITE("VTT for ");
2193 return ParseType();
2194 case 'I':
2195 WRITE("typeinfo for ");
2196 return ParseType();
2197 case 'S':
2198 WRITE("typeinfo name for ");
2199 return ParseType();
2200 case 'c':
2201 case 'C':
2202#ifdef DEBUG_FAILURES
Jason Molenda026aa492014-10-15 22:11:15 +00002203 printf("*** Unsupported thunk or construction vtable name: %.3s\n", m_read_ptr - 1);
Kate Stonee2b21862014-07-22 17:03:38 +00002204#endif
2205 return false;
2206 default:
Jason Molenda026aa492014-10-15 22:11:15 +00002207 if (*--m_read_ptr == 'v')
Kate Stonee2b21862014-07-22 17:03:38 +00002208 {
2209 WRITE("virtual thunk to ");
2210 }
2211 else
2212 {
2213 WRITE("non-virtual thunk to ");
2214 }
Jason Molenda026aa492014-10-15 22:11:15 +00002215 if (!ParseCallOffset())
2216 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002217 return ParseEncoding();
2218 }
2219 }
Jason Molenda026aa492014-10-15 22:11:15 +00002220
Kate Stonee2b21862014-07-22 17:03:38 +00002221 // <special-name> ::= GV <object name> # Guard variable for one-time initialization
2222 // # No <type>
2223 // extension ::= GR <object name> # reference temporary for object
Jason Molenda026aa492014-10-15 22:11:15 +00002224
2225 bool
2226 ParseSpecialNameG()
Kate Stonee2b21862014-07-22 17:03:38 +00002227 {
Jason Molenda026aa492014-10-15 22:11:15 +00002228 switch (*m_read_ptr++)
Kate Stonee2b21862014-07-22 17:03:38 +00002229 {
2230 case 'V':
2231 WRITE("guard variable for ");
Jason Molenda026aa492014-10-15 22:11:15 +00002232 if (!ParseName(true))
2233 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002234 break;
2235 case 'R':
2236 WRITE("reference temporary for ");
Jason Molenda026aa492014-10-15 22:11:15 +00002237 if (!ParseName(true))
2238 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002239 break;
2240 default:
2241#ifdef DEBUG_FAILURES
2242 printf("*** Unknown G encoding\n");
2243#endif
2244 return false;
2245 }
2246 return true;
2247 }
Jason Molenda026aa492014-10-15 22:11:15 +00002248
Kate Stonee2b21862014-07-22 17:03:38 +00002249 // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types
Jason Molenda026aa492014-10-15 22:11:15 +00002250
2251 bool
2252 ParseFunctionArgs(NameState & name_state, int return_insert_cookie)
Kate Stonee2b21862014-07-22 17:03:38 +00002253 {
Jason Molenda026aa492014-10-15 22:11:15 +00002254 char next = *m_read_ptr;
2255 if (next == 'E' || next == '\0' || next == '.')
2256 return true;
2257
Kate Stonee2b21862014-07-22 17:03:38 +00002258 // Clang has a bad habit of making unique manglings by just sticking numbers on the end of a symbol,
2259 // which is ambiguous with malformed source name manglings
Jason Molenda026aa492014-10-15 22:11:15 +00002260 const char *before_clang_uniquing_test = m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002261 if (TryParseNumber())
2262 {
Jason Molenda026aa492014-10-15 22:11:15 +00002263 if (*m_read_ptr == '\0')
2264 return true;
2265 m_read_ptr = before_clang_uniquing_test;
Kate Stonee2b21862014-07-22 17:03:38 +00002266 }
Jason Molenda026aa492014-10-15 22:11:15 +00002267
Kate Stonee2b21862014-07-22 17:03:38 +00002268 if (name_state.is_last_generic && !name_state.has_no_return_type)
2269 {
2270 int return_type_start_cookie = GetStartCookie();
Jason Molenda026aa492014-10-15 22:11:15 +00002271 if (!ParseType())
2272 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002273 Write(' ');
2274 ReorderRange(EndRange(return_type_start_cookie),
2275 return_insert_cookie);
2276 }
Jason Molenda026aa492014-10-15 22:11:15 +00002277
Kate Stonee2b21862014-07-22 17:03:38 +00002278 Write('(');
2279 bool first_param = true;
2280 while (true)
2281 {
Jason Molenda026aa492014-10-15 22:11:15 +00002282 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002283 {
2284 case '\0':
2285 case 'E':
2286 case '.':
2287 break;
2288 case 'v':
Jason Molenda026aa492014-10-15 22:11:15 +00002289 ++m_read_ptr;
Kate Stonee2b21862014-07-22 17:03:38 +00002290 continue;
2291 case '_':
2292 // Not a formal part of the mangling specification, but clang emits suffixes starting with _block_invoke
Jason Molenda026aa492014-10-15 22:11:15 +00002293 if (strncmp(m_read_ptr, "_block_invoke", 13) == 0)
Kate Stonee2b21862014-07-22 17:03:38 +00002294 {
Jason Molenda026aa492014-10-15 22:11:15 +00002295 m_read_ptr += strlen(m_read_ptr);
Kate Stonee2b21862014-07-22 17:03:38 +00002296 break;
2297 }
Jason Molenda62e06812016-02-16 04:14:33 +00002298 LLVM_FALLTHROUGH;
Kate Stonee2b21862014-07-22 17:03:38 +00002299 default:
Jason Molenda026aa492014-10-15 22:11:15 +00002300 if (first_param)
2301 first_param = false;
Kate Stonee2b21862014-07-22 17:03:38 +00002302 else WriteCommaSpace();
Jason Molenda026aa492014-10-15 22:11:15 +00002303
2304 if (!ParseType())
2305 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002306 continue;
2307 }
2308 break;
2309 }
2310 Write(')');
2311 return true;
2312 }
Jason Molenda026aa492014-10-15 22:11:15 +00002313
Kate Stonee2b21862014-07-22 17:03:38 +00002314 // <encoding> ::= <function name> <bare-function-type>
2315 // ::= <data name>
2316 // ::= <special-name>
Jason Molenda026aa492014-10-15 22:11:15 +00002317
2318 bool
2319 ParseEncoding()
Kate Stonee2b21862014-07-22 17:03:38 +00002320 {
Jason Molenda026aa492014-10-15 22:11:15 +00002321 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002322 {
2323 case 'T':
Jason Molenda026aa492014-10-15 22:11:15 +00002324 ++m_read_ptr;
2325 if (!ParseSpecialNameT())
2326 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002327 break;
2328 case 'G':
Jason Molenda026aa492014-10-15 22:11:15 +00002329 ++m_read_ptr;
2330 if (!ParseSpecialNameG())
2331 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002332 break;
2333 default:
Jason Molenda026aa492014-10-15 22:11:15 +00002334 if (!ParseName(true))
2335 return false;
Kate Stonee2b21862014-07-22 17:03:38 +00002336 break;
2337 }
2338 return true;
2339 }
Jason Molenda026aa492014-10-15 22:11:15 +00002340
2341 bool
2342 ParseMangling(const char *mangled_name, long mangled_name_length = 0)
Kate Stonee2b21862014-07-22 17:03:38 +00002343 {
Jason Molenda026aa492014-10-15 22:11:15 +00002344 if (!mangled_name_length)
2345 mangled_name_length = strlen(mangled_name);
2346 m_read_end = mangled_name + mangled_name_length;
2347 m_read_ptr = mangled_name;
2348 m_write_ptr = m_buffer;
2349 m_next_substitute_index = 0;
2350 m_next_template_arg_index = m_rewrite_ranges_size - 1;
2351
2352 if (*m_read_ptr++ != '_' || *m_read_ptr++ != 'Z')
Kate Stonee2b21862014-07-22 17:03:38 +00002353 {
2354#ifdef DEBUG_FAILURES
2355 printf("*** Missing _Z prefix\n");
2356#endif
2357 return false;
2358 }
Jason Molenda026aa492014-10-15 22:11:15 +00002359 if (!ParseEncoding())
2360 return false;
2361 switch (*m_read_ptr)
Kate Stonee2b21862014-07-22 17:03:38 +00002362 {
2363 case '.':
2364 Write(' ');
2365 Write('(');
Jason Molenda026aa492014-10-15 22:11:15 +00002366 Write(m_read_ptr, m_read_end - m_read_ptr);
Kate Stonee2b21862014-07-22 17:03:38 +00002367 Write(')');
2368 case '\0':
2369 return true;
2370 default:
2371#ifdef DEBUG_FAILURES
2372 printf("*** Unparsed mangled content\n");
2373#endif
2374 return false;
2375 }
2376 }
Jason Molenda026aa492014-10-15 22:11:15 +00002377
Kate Stonee2b21862014-07-22 17:03:38 +00002378private:
Jason Molenda026aa492014-10-15 22:11:15 +00002379
Kate Stonee2b21862014-07-22 17:03:38 +00002380 // External scratch storage used during demanglings
Jason Molenda026aa492014-10-15 22:11:15 +00002381
2382 char *m_buffer;
2383 const char *m_buffer_end;
2384 BufferRange *m_rewrite_ranges;
2385 int m_rewrite_ranges_size;
2386 bool m_owns_buffer;
2387 bool m_owns_m_rewrite_ranges;
2388
Kate Stonee2b21862014-07-22 17:03:38 +00002389 // Internal state used during demangling
Jason Molenda026aa492014-10-15 22:11:15 +00002390
2391 const char *m_read_ptr;
2392 const char *m_read_end;
2393 char *m_write_ptr;
2394 int m_next_template_arg_index;
2395 int m_next_substitute_index;
Kate Stonee2b21862014-07-22 17:03:38 +00002396};
2397
2398} // Anonymous namespace
2399
2400// Public entry points referenced from Mangled.cpp
2401namespace lldb_private
2402{
Jason Molenda026aa492014-10-15 22:11:15 +00002403 char *
2404 FastDemangle(const char *mangled_name)
Kate Stonee2b21862014-07-22 17:03:38 +00002405 {
2406 char buffer[16384];
Jason Molenda026aa492014-10-15 22:11:15 +00002407 SymbolDemangler demangler(buffer, sizeof (buffer));
Kate Stonee2b21862014-07-22 17:03:38 +00002408 return demangler.GetDemangledCopy(mangled_name);
2409 }
2410
Jason Molenda026aa492014-10-15 22:11:15 +00002411 char *
2412 FastDemangle(const char *mangled_name, long mangled_name_length)
Kate Stonee2b21862014-07-22 17:03:38 +00002413 {
2414 char buffer[16384];
Jason Molenda026aa492014-10-15 22:11:15 +00002415 SymbolDemangler demangler(buffer, sizeof (buffer));
Kate Stonee2b21862014-07-22 17:03:38 +00002416 return demangler.GetDemangledCopy(mangled_name, mangled_name_length);
2417 }
2418} // lldb_private namespace