blob: f1ad815ac4a5a27b6bfaf221e650e4b1b24484e4 [file] [log] [blame]
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001//===-------------------------- cxa_demangle.cpp --------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Howard Hinnant6c33e762013-06-17 18:10:34 +000010#define _LIBCPP_EXTERN_TEMPLATE(...)
11#define _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd213ffd2011-05-05 15:27:28 +000012
Howard Hinnant6c33e762013-06-17 18:10:34 +000013#include <vector>
Howard Hinnantd213ffd2011-05-05 15:27:28 +000014#include <algorithm>
Howard Hinnantd213ffd2011-05-05 15:27:28 +000015#include <string>
Howard Hinnant6c33e762013-06-17 18:10:34 +000016#include <numeric>
17#include <cstdlib>
18#include <cstring>
19#include <cctype>
Howard Hinnantd213ffd2011-05-05 15:27:28 +000020
Nico Weberb4c998b2015-09-20 18:10:46 +000021#ifdef _MSC_VER
22// snprintf is implemented in VS 2015
23#if _MSC_VER < 1900
24#define snprintf _snprintf_s
25#endif
26#endif
27
Howard Hinnantd213ffd2011-05-05 15:27:28 +000028namespace __cxxabiv1
29{
30
Howard Hinnant6c33e762013-06-17 18:10:34 +000031namespace
Howard Hinnantd213ffd2011-05-05 15:27:28 +000032{
33
Howard Hinnant6c33e762013-06-17 18:10:34 +000034enum
Howard Hinnantd213ffd2011-05-05 15:27:28 +000035{
Howard Hinnant6c33e762013-06-17 18:10:34 +000036 unknown_error = -4,
37 invalid_args = -3,
38 invalid_mangled_name,
39 memory_alloc_failure,
40 success
Howard Hinnantd213ffd2011-05-05 15:27:28 +000041};
42
Howard Hinnant6c33e762013-06-17 18:10:34 +000043template <class C>
44 const char* parse_type(const char* first, const char* last, C& db);
45template <class C>
46 const char* parse_encoding(const char* first, const char* last, C& db);
47template <class C>
Richard Smith24ecd092014-05-12 18:44:13 +000048 const char* parse_name(const char* first, const char* last, C& db,
49 bool* ends_with_template_args = 0);
Howard Hinnant6c33e762013-06-17 18:10:34 +000050template <class C>
51 const char* parse_expression(const char* first, const char* last, C& db);
52template <class C>
53 const char* parse_template_args(const char* first, const char* last, C& db);
54template <class C>
55 const char* parse_operator_name(const char* first, const char* last, C& db);
56template <class C>
57 const char* parse_unqualified_name(const char* first, const char* last, C& db);
58template <class C>
59 const char* parse_decltype(const char* first, const char* last, C& db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +000060
Howard Hinnant6c33e762013-06-17 18:10:34 +000061template <class C>
62void
63print_stack(const C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +000064{
Ed Schouten196cbd72015-03-19 09:17:21 +000065 fprintf(stderr, "---------\n");
66 fprintf(stderr, "names:\n");
Howard Hinnant6c33e762013-06-17 18:10:34 +000067 for (auto& s : db.names)
Ed Schouten196cbd72015-03-19 09:17:21 +000068 fprintf(stderr, "{%s#%s}\n", s.first.c_str(), s.second.c_str());
Howard Hinnant6c33e762013-06-17 18:10:34 +000069 int i = -1;
Ed Schouten196cbd72015-03-19 09:17:21 +000070 fprintf(stderr, "subs:\n");
Howard Hinnant6c33e762013-06-17 18:10:34 +000071 for (auto& v : db.subs)
Howard Hinnantd213ffd2011-05-05 15:27:28 +000072 {
Howard Hinnant6c33e762013-06-17 18:10:34 +000073 if (i >= 0)
Ed Schouten196cbd72015-03-19 09:17:21 +000074 fprintf(stderr, "S%i_ = {", i);
Howard Hinnant6c33e762013-06-17 18:10:34 +000075 else
Ed Schouten196cbd72015-03-19 09:17:21 +000076 fprintf(stderr, "S_ = {");
Howard Hinnant6c33e762013-06-17 18:10:34 +000077 for (auto& s : v)
Ed Schouten196cbd72015-03-19 09:17:21 +000078 fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str());
79 fprintf(stderr, "}\n");
Howard Hinnant6c33e762013-06-17 18:10:34 +000080 ++i;
Howard Hinnantd213ffd2011-05-05 15:27:28 +000081 }
Ed Schouten196cbd72015-03-19 09:17:21 +000082 fprintf(stderr, "template_param:\n");
Howard Hinnant6c33e762013-06-17 18:10:34 +000083 for (auto& t : db.template_param)
84 {
Ed Schouten196cbd72015-03-19 09:17:21 +000085 fprintf(stderr, "--\n");
Howard Hinnant6c33e762013-06-17 18:10:34 +000086 i = -1;
87 for (auto& v : t)
88 {
89 if (i >= 0)
Ed Schouten196cbd72015-03-19 09:17:21 +000090 fprintf(stderr, "T%i_ = {", i);
Howard Hinnant6c33e762013-06-17 18:10:34 +000091 else
Ed Schouten196cbd72015-03-19 09:17:21 +000092 fprintf(stderr, "T_ = {");
Howard Hinnant6c33e762013-06-17 18:10:34 +000093 for (auto& s : v)
Ed Schouten196cbd72015-03-19 09:17:21 +000094 fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str());
95 fprintf(stderr, "}\n");
Howard Hinnant6c33e762013-06-17 18:10:34 +000096 ++i;
97 }
98 }
Ed Schouten196cbd72015-03-19 09:17:21 +000099 fprintf(stderr, "---------\n\n");
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000100}
101
Howard Hinnant6c33e762013-06-17 18:10:34 +0000102template <class C>
103void
104print_state(const char* msg, const char* first, const char* last, const C& db)
Howard Hinnant5dd173b2013-04-10 19:44:03 +0000105{
Ed Schouten196cbd72015-03-19 09:17:21 +0000106 fprintf(stderr, "%s: ", msg);
Howard Hinnant6c33e762013-06-17 18:10:34 +0000107 for (; first != last; ++first)
Ed Schouten196cbd72015-03-19 09:17:21 +0000108 fprintf(stderr, "%c", *first);
109 fprintf(stderr, "\n");
Howard Hinnant6c33e762013-06-17 18:10:34 +0000110 print_stack(db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000111}
112
Howard Hinnant6c33e762013-06-17 18:10:34 +0000113// <number> ::= [n] <non-negative decimal integer>
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000114
115const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +0000116parse_number(const char* first, const char* last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000117{
Howard Hinnant6c33e762013-06-17 18:10:34 +0000118 if (first != last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000119 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000120 const char* t = first;
121 if (*t == 'n')
122 ++t;
123 if (t != last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000124 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000125 if (*t == '0')
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000126 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000127 first = t+1;
128 }
129 else if ('1' <= *t && *t <= '9')
130 {
131 first = t+1;
132 while (first != last && std::isdigit(*first))
133 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000134 }
135 }
136 }
Howard Hinnant6c33e762013-06-17 18:10:34 +0000137 return first;
138}
139
140template <class Float>
141struct float_data;
142
143template <>
144struct float_data<float>
145{
146 static const size_t mangled_size = 8;
147 static const size_t max_demangled_size = 24;
Howard Hinnantc62cbea2013-06-17 20:25:21 +0000148 static constexpr const char* spec = "%af";
Howard Hinnant6c33e762013-06-17 18:10:34 +0000149};
150
151constexpr const char* float_data<float>::spec;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000152
153template <>
154struct float_data<double>
155{
156 static const size_t mangled_size = 16;
157 static const size_t max_demangled_size = 32;
158 static constexpr const char* spec = "%a";
Howard Hinnant6c33e762013-06-17 18:10:34 +0000159};
160
161constexpr const char* float_data<double>::spec;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000162
163template <>
164struct float_data<long double>
165{
Renato Golinf704b662015-08-19 15:24:03 +0000166#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__)
Daniel Sanders52cf98b2015-07-30 16:11:04 +0000167 static const size_t mangled_size = 32;
168#elif defined(__arm__) || defined(__mips__)
Logan Chien05d51bc2014-05-10 00:42:10 +0000169 static const size_t mangled_size = 16;
170#else
Howard Hinnant6c33e762013-06-17 18:10:34 +0000171 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
Logan Chien05d51bc2014-05-10 00:42:10 +0000172#endif
Howard Hinnant6c33e762013-06-17 18:10:34 +0000173 static const size_t max_demangled_size = 40;
Howard Hinnantc62cbea2013-06-17 20:25:21 +0000174 static constexpr const char* spec = "%LaL";
Howard Hinnant6c33e762013-06-17 18:10:34 +0000175};
176
177constexpr const char* float_data<long double>::spec;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000178
179template <class Float, class C>
180const char*
181parse_floating_number(const char* first, const char* last, C& db)
182{
183 const size_t N = float_data<Float>::mangled_size;
184 if (static_cast<std::size_t>(last - first) > N)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000185 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000186 last = first + N;
187 union
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000188 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000189 Float value;
190 char buf[sizeof(Float)];
191 };
192 const char* t = first;
193 char* e = buf;
194 for (; t != last; ++t, ++e)
195 {
196 if (!isxdigit(*t))
197 return first;
198 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0') :
199 static_cast<unsigned>(*t - 'a' + 10);
200 ++t;
201 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0') :
202 static_cast<unsigned>(*t - 'a' + 10);
203 *e = static_cast<char>((d1 << 4) + d0);
204 }
205 if (*t == 'E')
206 {
Saleem Abdulrasool2493be62015-04-27 02:21:52 +0000207#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
Howard Hinnant6c33e762013-06-17 18:10:34 +0000208 std::reverse(buf, e);
209#endif
210 char num[float_data<Float>::max_demangled_size] = {0};
Howard Hinnantc62cbea2013-06-17 20:25:21 +0000211 int n = snprintf(num, sizeof(num), float_data<Float>::spec, value);
212 if (static_cast<std::size_t>(n) >= sizeof(num))
213 return first;
214 db.names.push_back(typename C::String(num, static_cast<std::size_t>(n)));
Howard Hinnant6c33e762013-06-17 18:10:34 +0000215 first = t+1;
216 }
217 }
218 return first;
219}
220
221// <source-name> ::= <positive length number> <identifier>
222
223template <class C>
224const char*
225parse_source_name(const char* first, const char* last, C& db)
226{
227 if (first != last)
228 {
229 char c = *first;
230 if (isdigit(c) && first+1 != last)
231 {
232 const char* t = first+1;
233 size_t n = static_cast<size_t>(c - '0');
234 for (c = *t; isdigit(c); c = *t)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000235 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000236 n = n * 10 + static_cast<size_t>(c - '0');
237 if (++t == last)
238 return first;
239 }
240 if (static_cast<size_t>(last - t) >= n)
241 {
242 typename C::String r(t, n);
243 if (r.substr(0, 10) == "_GLOBAL__N")
244 db.names.push_back("(anonymous namespace)");
245 else
246 db.names.push_back(std::move(r));
247 first = t + n;
248 }
249 }
250 }
251 return first;
252}
253
254// <substitution> ::= S <seq-id> _
255// ::= S_
256// <substitution> ::= Sa # ::std::allocator
257// <substitution> ::= Sb # ::std::basic_string
258// <substitution> ::= Ss # ::std::basic_string < char,
259// ::std::char_traits<char>,
260// ::std::allocator<char> >
261// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
262// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
263// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
264
265template <class C>
266const char*
267parse_substitution(const char* first, const char* last, C& db)
268{
269 if (last - first >= 2)
270 {
271 if (*first == 'S')
272 {
273 switch (first[1])
274 {
275 case 'a':
276 db.names.push_back("std::allocator");
277 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000278 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000279 case 'b':
280 db.names.push_back("std::basic_string");
281 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000282 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000283 case 's':
284 db.names.push_back("std::string");
285 first += 2;
286 break;
287 case 'i':
288 db.names.push_back("std::istream");
289 first += 2;
290 break;
291 case 'o':
292 db.names.push_back("std::ostream");
293 first += 2;
294 break;
295 case 'd':
296 db.names.push_back("std::iostream");
297 first += 2;
298 break;
299 case '_':
300 if (!db.subs.empty())
301 {
302 for (const auto& n : db.subs.front())
303 db.names.push_back(n);
304 first += 2;
305 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000306 break;
307 default:
Howard Hinnant6c33e762013-06-17 18:10:34 +0000308 if (std::isdigit(first[1]) || std::isupper(first[1]))
309 {
310 size_t sub = 0;
311 const char* t = first+1;
312 if (std::isdigit(*t))
313 sub = static_cast<size_t>(*t - '0');
314 else
315 sub = static_cast<size_t>(*t - 'A') + 10;
316 for (++t; t != last && (std::isdigit(*t) || std::isupper(*t)); ++t)
317 {
318 sub *= 36;
319 if (std::isdigit(*t))
320 sub += static_cast<size_t>(*t - '0');
321 else
322 sub += static_cast<size_t>(*t - 'A') + 10;
323 }
324 if (t == last || *t != '_')
325 return first;
326 ++sub;
327 if (sub < db.subs.size())
328 {
329 for (const auto& n : db.subs[sub])
330 db.names.push_back(n);
331 first = t+1;
332 }
333 }
334 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000335 }
336 }
337 }
338 return first;
339}
340
341// <builtin-type> ::= v # void
342// ::= w # wchar_t
343// ::= b # bool
344// ::= c # char
345// ::= a # signed char
346// ::= h # unsigned char
347// ::= s # short
348// ::= t # unsigned short
349// ::= i # int
350// ::= j # unsigned int
351// ::= l # long
352// ::= m # unsigned long
353// ::= x # long long, __int64
354// ::= y # unsigned long long, __int64
355// ::= n # __int128
356// ::= o # unsigned __int128
357// ::= f # float
358// ::= d # double
359// ::= e # long double, __float80
360// ::= g # __float128
361// ::= z # ellipsis
362// ::= Dd # IEEE 754r decimal floating point (64 bits)
363// ::= De # IEEE 754r decimal floating point (128 bits)
364// ::= Df # IEEE 754r decimal floating point (32 bits)
365// ::= Dh # IEEE 754r half-precision floating point (16 bits)
366// ::= Di # char32_t
367// ::= Ds # char16_t
368// ::= Da # auto (in dependent new-expressions)
Anders Carlsson2950e562014-02-17 21:56:01 +0000369// ::= Dc # decltype(auto)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000370// ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
371// ::= u <source-name> # vendor extended type
372
Howard Hinnant6c33e762013-06-17 18:10:34 +0000373template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000374const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +0000375parse_builtin_type(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000376{
377 if (first != last)
378 {
379 switch (*first)
380 {
381 case 'v':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000382 db.names.push_back("void");
383 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000384 break;
385 case 'w':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000386 db.names.push_back("wchar_t");
387 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000388 break;
389 case 'b':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000390 db.names.push_back("bool");
391 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000392 break;
393 case 'c':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000394 db.names.push_back("char");
395 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000396 break;
397 case 'a':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000398 db.names.push_back("signed char");
399 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000400 break;
401 case 'h':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000402 db.names.push_back("unsigned char");
403 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000404 break;
405 case 's':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000406 db.names.push_back("short");
407 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000408 break;
409 case 't':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000410 db.names.push_back("unsigned short");
411 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000412 break;
413 case 'i':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000414 db.names.push_back("int");
415 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000416 break;
417 case 'j':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000418 db.names.push_back("unsigned int");
419 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000420 break;
421 case 'l':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000422 db.names.push_back("long");
423 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000424 break;
425 case 'm':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000426 db.names.push_back("unsigned long");
427 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000428 break;
429 case 'x':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000430 db.names.push_back("long long");
431 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000432 break;
433 case 'y':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000434 db.names.push_back("unsigned long long");
435 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000436 break;
437 case 'n':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000438 db.names.push_back("__int128");
439 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000440 break;
441 case 'o':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000442 db.names.push_back("unsigned __int128");
443 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000444 break;
445 case 'f':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000446 db.names.push_back("float");
447 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000448 break;
449 case 'd':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000450 db.names.push_back("double");
451 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000452 break;
453 case 'e':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000454 db.names.push_back("long double");
455 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000456 break;
457 case 'g':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000458 db.names.push_back("__float128");
459 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000460 break;
461 case 'z':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000462 db.names.push_back("...");
463 ++first;
464 break;
465 case 'u':
466 {
467 const char*t = parse_source_name(first+1, last, db);
468 if (t != first+1)
469 first = t;
470 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000471 break;
472 case 'D':
473 if (first+1 != last)
474 {
475 switch (first[1])
476 {
477 case 'd':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000478 db.names.push_back("decimal64");
479 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000480 break;
481 case 'e':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000482 db.names.push_back("decimal128");
483 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000484 break;
485 case 'f':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000486 db.names.push_back("decimal32");
487 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000488 break;
489 case 'h':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000490 db.names.push_back("decimal16");
491 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000492 break;
493 case 'i':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000494 db.names.push_back("char32_t");
495 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000496 break;
497 case 's':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000498 db.names.push_back("char16_t");
499 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000500 break;
501 case 'a':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000502 db.names.push_back("auto");
503 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000504 break;
Anders Carlsson2950e562014-02-17 21:56:01 +0000505 case 'c':
506 db.names.push_back("decltype(auto)");
507 first += 2;
508 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000509 case 'n':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000510 db.names.push_back("std::nullptr_t");
511 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000512 break;
513 }
514 }
515 break;
516 }
517 }
518 return first;
519}
520
Howard Hinnant6c33e762013-06-17 18:10:34 +0000521// <CV-qualifiers> ::= [r] [V] [K]
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000522
523const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +0000524parse_cv_qualifiers(const char* first, const char* last, unsigned& cv)
525{
526 cv = 0;
527 if (first != last)
528 {
529 if (*first == 'r')
530 {
531 cv |= 4;
532 ++first;
533 }
534 if (*first == 'V')
535 {
536 cv |= 2;
537 ++first;
538 }
539 if (*first == 'K')
540 {
541 cv |= 1;
542 ++first;
543 }
544 }
545 return first;
546}
547
548// <template-param> ::= T_ # first template parameter
549// ::= T <parameter-2 non-negative number> _
550
551template <class C>
552const char*
553parse_template_param(const char* first, const char* last, C& db)
554{
555 if (last - first >= 2)
556 {
557 if (*first == 'T')
558 {
559 if (first[1] == '_')
560 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000561 if (db.template_param.empty())
562 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000563 if (!db.template_param.back().empty())
564 {
565 for (auto& t : db.template_param.back().front())
566 db.names.push_back(t);
567 first += 2;
568 }
569 else
570 {
Howard Hinnantb2d1f942013-06-23 19:52:45 +0000571 db.names.push_back("T_");
Howard Hinnant6c33e762013-06-17 18:10:34 +0000572 first += 2;
573 db.fix_forward_references = true;
574 }
575 }
576 else if (isdigit(first[1]))
577 {
578 const char* t = first+1;
579 size_t sub = static_cast<size_t>(*t - '0');
580 for (++t; t != last && isdigit(*t); ++t)
581 {
582 sub *= 10;
583 sub += static_cast<size_t>(*t - '0');
584 }
Howard Hinnant753a30d2013-12-11 19:44:25 +0000585 if (t == last || *t != '_' || db.template_param.empty())
Howard Hinnant6c33e762013-06-17 18:10:34 +0000586 return first;
587 ++sub;
588 if (sub < db.template_param.back().size())
589 {
590 for (auto& temp : db.template_param.back()[sub])
591 db.names.push_back(temp);
592 first = t+1;
593 }
594 else
595 {
Howard Hinnantb2d1f942013-06-23 19:52:45 +0000596 db.names.push_back(typename C::String(first, t+1));
Howard Hinnant6c33e762013-06-17 18:10:34 +0000597 first = t+1;
598 db.fix_forward_references = true;
599 }
600 }
601 }
602 }
603 return first;
604}
605
606// cc <type> <expression> # const_cast<type> (expression)
607
608template <class C>
609const char*
610parse_const_cast_expr(const char* first, const char* last, C& db)
611{
612 if (last - first >= 3 && first[0] == 'c' && first[1] == 'c')
613 {
614 const char* t = parse_type(first+2, last, db);
615 if (t != first+2)
616 {
617 const char* t1 = parse_expression(t, last, db);
618 if (t1 != t)
619 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000620 if (db.names.size() < 2)
621 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000622 auto expr = db.names.back().move_full();
623 db.names.pop_back();
624 db.names.back() = "const_cast<" + db.names.back().move_full() + ">(" + expr + ")";
625 first = t1;
626 }
627 }
628 }
629 return first;
630}
631
632// dc <type> <expression> # dynamic_cast<type> (expression)
633
634template <class C>
635const char*
636parse_dynamic_cast_expr(const char* first, const char* last, C& db)
637{
638 if (last - first >= 3 && first[0] == 'd' && first[1] == 'c')
639 {
640 const char* t = parse_type(first+2, last, db);
641 if (t != first+2)
642 {
643 const char* t1 = parse_expression(t, last, db);
644 if (t1 != t)
645 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000646 if (db.names.size() < 2)
647 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000648 auto expr = db.names.back().move_full();
649 db.names.pop_back();
650 db.names.back() = "dynamic_cast<" + db.names.back().move_full() + ">(" + expr + ")";
651 first = t1;
652 }
653 }
654 }
655 return first;
656}
657
658// rc <type> <expression> # reinterpret_cast<type> (expression)
659
660template <class C>
661const char*
662parse_reinterpret_cast_expr(const char* first, const char* last, C& db)
663{
664 if (last - first >= 3 && first[0] == 'r' && first[1] == 'c')
665 {
666 const char* t = parse_type(first+2, last, db);
667 if (t != first+2)
668 {
669 const char* t1 = parse_expression(t, last, db);
670 if (t1 != t)
671 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000672 if (db.names.size() < 2)
673 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000674 auto expr = db.names.back().move_full();
675 db.names.pop_back();
676 db.names.back() = "reinterpret_cast<" + db.names.back().move_full() + ">(" + expr + ")";
677 first = t1;
678 }
679 }
680 }
681 return first;
682}
683
684// sc <type> <expression> # static_cast<type> (expression)
685
686template <class C>
687const char*
688parse_static_cast_expr(const char* first, const char* last, C& db)
689{
690 if (last - first >= 3 && first[0] == 's' && first[1] == 'c')
691 {
692 const char* t = parse_type(first+2, last, db);
693 if (t != first+2)
694 {
695 const char* t1 = parse_expression(t, last, db);
696 if (t1 != t)
697 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000698 if (db.names.size() < 2)
699 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000700 auto expr = db.names.back().move_full();
701 db.names.pop_back();
702 db.names.back() = "static_cast<" + db.names.back().move_full() + ">(" + expr + ")";
703 first = t1;
704 }
705 }
706 }
707 return first;
708}
709
710// sp <expression> # pack expansion
711
712template <class C>
713const char*
714parse_pack_expansion(const char* first, const char* last, C& db)
715{
716 if (last - first >= 3 && first[0] == 's' && first[1] == 'p')
717 {
718 const char* t = parse_expression(first+2, last, db);
719 if (t != first+2)
720 first = t;
721 }
722 return first;
723}
724
725// st <type> # sizeof (a type)
726
727template <class C>
728const char*
729parse_sizeof_type_expr(const char* first, const char* last, C& db)
730{
731 if (last - first >= 3 && first[0] == 's' && first[1] == 't')
732 {
733 const char* t = parse_type(first+2, last, db);
734 if (t != first+2)
735 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000736 if (db.names.empty())
737 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000738 db.names.back() = "sizeof (" + db.names.back().move_full() + ")";
739 first = t;
740 }
741 }
742 return first;
743}
744
745// sz <expr> # sizeof (a expression)
746
747template <class C>
748const char*
749parse_sizeof_expr_expr(const char* first, const char* last, C& db)
750{
751 if (last - first >= 3 && first[0] == 's' && first[1] == 'z')
752 {
753 const char* t = parse_expression(first+2, last, db);
754 if (t != first+2)
755 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000756 if (db.names.empty())
757 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000758 db.names.back() = "sizeof (" + db.names.back().move_full() + ")";
759 first = t;
760 }
761 }
762 return first;
763}
764
765// sZ <template-param> # size of a parameter pack
766
767template <class C>
768const char*
769parse_sizeof_param_pack_expr(const char* first, const char* last, C& db)
770{
771 if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' && first[2] == 'T')
772 {
773 size_t k0 = db.names.size();
774 const char* t = parse_template_param(first+2, last, db);
775 size_t k1 = db.names.size();
776 if (t != first+2)
777 {
778 typename C::String tmp("sizeof...(");
779 size_t k = k0;
780 if (k != k1)
781 {
782 tmp += db.names[k].move_full();
783 for (++k; k != k1; ++k)
784 tmp += ", " + db.names[k].move_full();
785 }
786 tmp += ")";
787 for (; k1 != k0; --k1)
788 db.names.pop_back();
789 db.names.push_back(std::move(tmp));
790 first = t;
791 }
792 }
793 return first;
794}
795
796// <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, first parameter
797// ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
798// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _ # L > 0, first parameter
799// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
800
801template <class C>
802const char*
803parse_function_param(const char* first, const char* last, C& db)
804{
805 if (last - first >= 3 && *first == 'f')
806 {
807 if (first[1] == 'p')
808 {
809 unsigned cv;
810 const char* t = parse_cv_qualifiers(first+2, last, cv);
811 const char* t1 = parse_number(t, last);
812 if (t1 != last && *t1 == '_')
813 {
814 db.names.push_back("fp" + typename C::String(t, t1));
815 first = t1+1;
816 }
817 }
818 else if (first[1] == 'L')
819 {
820 unsigned cv;
821 const char* t0 = parse_number(first+2, last);
822 if (t0 != last && *t0 == 'p')
823 {
824 ++t0;
825 const char* t = parse_cv_qualifiers(t0, last, cv);
826 const char* t1 = parse_number(t, last);
827 if (t1 != last && *t1 == '_')
828 {
829 db.names.push_back("fp" + typename C::String(t, t1));
830 first = t1+1;
831 }
832 }
833 }
834 }
835 return first;
836}
837
838// sZ <function-param> # size of a function parameter pack
839
840template <class C>
841const char*
842parse_sizeof_function_param_pack_expr(const char* first, const char* last, C& db)
843{
844 if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' && first[2] == 'f')
845 {
846 const char* t = parse_function_param(first+2, last, db);
847 if (t != first+2)
848 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000849 if (db.names.empty())
850 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000851 db.names.back() = "sizeof...(" + db.names.back().move_full() + ")";
852 first = t;
853 }
854 }
855 return first;
856}
857
858// te <expression> # typeid (expression)
859// ti <type> # typeid (type)
860
861template <class C>
862const char*
863parse_typeid_expr(const char* first, const char* last, C& db)
864{
865 if (last - first >= 3 && first[0] == 't' && (first[1] == 'e' || first[1] == 'i'))
866 {
867 const char* t;
868 if (first[1] == 'e')
869 t = parse_expression(first+2, last, db);
870 else
871 t = parse_type(first+2, last, db);
872 if (t != first+2)
873 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000874 if (db.names.empty())
875 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000876 db.names.back() = "typeid(" + db.names.back().move_full() + ")";
877 first = t;
878 }
879 }
880 return first;
881}
882
883// tw <expression> # throw expression
884
885template <class C>
886const char*
887parse_throw_expr(const char* first, const char* last, C& db)
888{
889 if (last - first >= 3 && first[0] == 't' && first[1] == 'w')
890 {
891 const char* t = parse_expression(first+2, last, db);
892 if (t != first+2)
893 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000894 if (db.names.empty())
895 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000896 db.names.back() = "throw " + db.names.back().move_full();
897 first = t;
898 }
899 }
900 return first;
901}
902
903// ds <expression> <expression> # expr.*expr
904
905template <class C>
906const char*
907parse_dot_star_expr(const char* first, const char* last, C& db)
908{
909 if (last - first >= 3 && first[0] == 'd' && first[1] == 's')
910 {
911 const char* t = parse_expression(first+2, last, db);
912 if (t != first+2)
913 {
914 const char* t1 = parse_expression(t, last, db);
915 if (t1 != t)
916 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000917 if (db.names.size() < 2)
918 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000919 auto expr = db.names.back().move_full();
920 db.names.pop_back();
921 db.names.back().first += ".*" + expr;
922 first = t1;
923 }
924 }
925 }
926 return first;
927}
928
929// <simple-id> ::= <source-name> [ <template-args> ]
930
931template <class C>
932const char*
933parse_simple_id(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000934{
935 if (first != last)
936 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000937 const char* t = parse_source_name(first, last, db);
938 if (t != first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000939 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000940 const char* t1 = parse_template_args(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000941 if (t1 != t)
942 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000943 if (db.names.size() < 2)
944 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000945 auto args = db.names.back().move_full();
946 db.names.pop_back();
947 db.names.back().first += std::move(args);
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000948 }
Howard Hinnant6c33e762013-06-17 18:10:34 +0000949 first = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000950 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000951 else
Howard Hinnant6c33e762013-06-17 18:10:34 +0000952 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000953 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000954 return first;
955}
956
Howard Hinnant6c33e762013-06-17 18:10:34 +0000957// <unresolved-type> ::= <template-param>
958// ::= <decltype>
959// ::= <substitution>
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000960
Howard Hinnant6c33e762013-06-17 18:10:34 +0000961template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000962const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +0000963parse_unresolved_type(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000964{
Howard Hinnant6c33e762013-06-17 18:10:34 +0000965 if (first != last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000966 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000967 const char* t = first;
968 switch (*first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000969 {
Howard Hinnant86ccacd2012-09-13 23:49:59 +0000970 case 'T':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000971 {
972 size_t k0 = db.names.size();
973 t = parse_template_param(first, last, db);
974 size_t k1 = db.names.size();
975 if (t != first && k1 == k0 + 1)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000976 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000977 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
978 first = t;
Howard Hinnantab039992012-08-01 18:56:46 +0000979 }
980 else
Howard Hinnant342f2f92012-11-30 18:43:50 +0000981 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000982 for (; k1 != k0; --k1)
983 db.names.pop_back();
Howard Hinnant342f2f92012-11-30 18:43:50 +0000984 }
Howard Hinnantab87dcf2011-12-15 20:02:15 +0000985 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000986 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000987 case 'D':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000988 t = parse_decltype(first, last, db);
989 if (t != first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000990 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000991 if (db.names.empty())
992 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000993 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
994 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000995 }
996 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000997 case 'S':
998 t = parse_substitution(first, last, db);
999 if (t != first)
1000 first = t;
1001 else
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001002 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001003 if (last - first > 2 && first[1] == 't')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001004 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001005 t = parse_unqualified_name(first+2, last, db);
1006 if (t != first+2)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001007 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001008 if (db.names.empty())
1009 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001010 db.names.back().first.insert(0, "std::");
1011 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
1012 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001013 }
1014 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001015 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001016 break;
1017 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001018 }
1019 return first;
1020}
1021
1022// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
1023// ::= <simple-id> # e.g., ~A<2*N>
1024
Howard Hinnant6c33e762013-06-17 18:10:34 +00001025template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001026const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001027parse_destructor_name(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001028{
1029 if (first != last)
1030 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001031 const char* t = parse_unresolved_type(first, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001032 if (t == first)
Howard Hinnant6c33e762013-06-17 18:10:34 +00001033 t = parse_simple_id(first, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001034 if (t != first)
Howard Hinnant6c33e762013-06-17 18:10:34 +00001035 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001036 if (db.names.empty())
1037 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001038 db.names.back().first.insert(0, "~");
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001039 first = t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001040 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001041 }
1042 return first;
1043}
1044
1045// <base-unresolved-name> ::= <simple-id> # unresolved name
1046// extension ::= <operator-name> # unresolved operator-function-id
1047// extension ::= <operator-name> <template-args> # unresolved operator template-id
1048// ::= on <operator-name> # unresolved operator-function-id
1049// ::= on <operator-name> <template-args> # unresolved operator template-id
1050// ::= dn <destructor-name> # destructor or pseudo-destructor;
1051// # e.g. ~X or ~X<N-1>
1052
Howard Hinnant6c33e762013-06-17 18:10:34 +00001053template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001054const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001055parse_base_unresolved_name(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001056{
1057 if (last - first >= 2)
1058 {
1059 if ((first[0] == 'o' || first[0] == 'd') && first[1] == 'n')
1060 {
1061 if (first[0] == 'o')
1062 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001063 const char* t = parse_operator_name(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001064 if (t != first+2)
Howard Hinnant6c33e762013-06-17 18:10:34 +00001065 {
1066 first = parse_template_args(t, last, db);
1067 if (first != t)
1068 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001069 if (db.names.size() < 2)
1070 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001071 auto args = db.names.back().move_full();
1072 db.names.pop_back();
1073 db.names.back().first += std::move(args);
1074 }
1075 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001076 }
1077 else
1078 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001079 const char* t = parse_destructor_name(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001080 if (t != first+2)
1081 first = t;
1082 }
1083 }
1084 else
1085 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001086 const char* t = parse_simple_id(first, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001087 if (t == first)
1088 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001089 t = parse_operator_name(first, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001090 if (t != first)
Howard Hinnant6c33e762013-06-17 18:10:34 +00001091 {
1092 first = parse_template_args(t, last, db);
1093 if (first != t)
1094 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001095 if (db.names.size() < 2)
1096 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001097 auto args = db.names.back().move_full();
1098 db.names.pop_back();
1099 db.names.back().first += std::move(args);
1100 }
1101 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001102 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001103 else
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001104 first = t;
1105 }
1106 }
1107 return first;
1108}
1109
Howard Hinnant6c33e762013-06-17 18:10:34 +00001110// <unresolved-qualifier-level> ::= <simple-id>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001111
Howard Hinnant6c33e762013-06-17 18:10:34 +00001112template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001113const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001114parse_unresolved_qualifier_level(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001115{
Howard Hinnant6c33e762013-06-17 18:10:34 +00001116 return parse_simple_id(first, last, db);
Howard Hinnant889b02d2011-06-22 19:27:39 +00001117}
1118
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001119// <unresolved-name>
Howard Hinnant889b02d2011-06-22 19:27:39 +00001120// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001121// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
1122// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
1123// # A::x, N::y, A<T>::z; "gs" means leading "::"
Howard Hinnant889b02d2011-06-22 19:27:39 +00001124// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
Howard Hinnant6c33e762013-06-17 18:10:34 +00001125// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
Howard Hinnant889b02d2011-06-22 19:27:39 +00001126// # T::N::x /decltype(p)::N::x
1127// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001128
Howard Hinnant6c33e762013-06-17 18:10:34 +00001129template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001130const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001131parse_unresolved_name(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001132{
1133 if (last - first > 2)
1134 {
Howard Hinnant889b02d2011-06-22 19:27:39 +00001135 const char* t = first;
1136 bool global = false;
1137 if (t[0] == 'g' && t[1] == 's')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001138 {
Howard Hinnant889b02d2011-06-22 19:27:39 +00001139 global = true;
1140 t += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001141 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001142 const char* t2 = parse_base_unresolved_name(t, last, db);
Howard Hinnant889b02d2011-06-22 19:27:39 +00001143 if (t2 != t)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001144 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001145 if (global)
Howard Hinnant753a30d2013-12-11 19:44:25 +00001146 {
1147 if (db.names.empty())
1148 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001149 db.names.back().first.insert(0, "::");
Howard Hinnant753a30d2013-12-11 19:44:25 +00001150 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001151 first = t2;
Howard Hinnant889b02d2011-06-22 19:27:39 +00001152 }
1153 else if (last - t > 2 && t[0] == 's' && t[1] == 'r')
1154 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001155 if (t[2] == 'N')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001156 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001157 t += 3;
1158 const char* t1 = parse_unresolved_type(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001159 if (t1 == t || t1 == last)
1160 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001161 t = t1;
1162 t1 = parse_template_args(t, last, db);
1163 if (t1 != t)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001164 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001165 if (db.names.size() < 2)
1166 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001167 auto args = db.names.back().move_full();
1168 db.names.pop_back();
1169 db.names.back().first += std::move(args);
1170 t = t1;
1171 if (t == last)
1172 {
1173 db.names.pop_back();
1174 return first;
1175 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001176 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001177 while (*t != 'E')
1178 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001179 t1 = parse_unresolved_qualifier_level(t, last, db);
Howard Hinnant753a30d2013-12-11 19:44:25 +00001180 if (t1 == t || t1 == last || db.names.size() < 2)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001181 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001182 auto s = db.names.back().move_full();
1183 db.names.pop_back();
1184 db.names.back().first += "::" + std::move(s);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001185 t = t1;
1186 }
1187 ++t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001188 t1 = parse_base_unresolved_name(t, last, db);
1189 if (t1 == t)
1190 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001191 if (!db.names.empty())
1192 db.names.pop_back();
Howard Hinnant6c33e762013-06-17 18:10:34 +00001193 return first;
1194 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00001195 if (db.names.size() < 2)
1196 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001197 auto s = db.names.back().move_full();
1198 db.names.pop_back();
1199 db.names.back().first += "::" + std::move(s);
1200 first = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001201 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001202 else
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001203 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001204 t += 2;
1205 const char* t1 = parse_unresolved_type(t, last, db);
1206 if (t1 != t)
1207 {
1208 t = t1;
1209 t1 = parse_template_args(t, last, db);
1210 if (t1 != t)
1211 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001212 if (db.names.size() < 2)
1213 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001214 auto args = db.names.back().move_full();
1215 db.names.pop_back();
1216 db.names.back().first += std::move(args);
1217 t = t1;
1218 }
1219 t1 = parse_base_unresolved_name(t, last, db);
1220 if (t1 == t)
1221 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001222 if (!db.names.empty())
1223 db.names.pop_back();
Howard Hinnant6c33e762013-06-17 18:10:34 +00001224 return first;
1225 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00001226 if (db.names.size() < 2)
1227 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001228 auto s = db.names.back().move_full();
1229 db.names.pop_back();
1230 db.names.back().first += "::" + std::move(s);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001231 first = t1;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001232 }
1233 else
1234 {
1235 t1 = parse_unresolved_qualifier_level(t, last, db);
1236 if (t1 == t || t1 == last)
1237 return first;
1238 t = t1;
1239 if (global)
Howard Hinnant753a30d2013-12-11 19:44:25 +00001240 {
1241 if (db.names.empty())
1242 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001243 db.names.back().first.insert(0, "::");
Howard Hinnant753a30d2013-12-11 19:44:25 +00001244 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001245 while (*t != 'E')
1246 {
1247 t1 = parse_unresolved_qualifier_level(t, last, db);
Howard Hinnant753a30d2013-12-11 19:44:25 +00001248 if (t1 == t || t1 == last || db.names.size() < 2)
Howard Hinnant6c33e762013-06-17 18:10:34 +00001249 return first;
1250 auto s = db.names.back().move_full();
1251 db.names.pop_back();
1252 db.names.back().first += "::" + std::move(s);
1253 t = t1;
1254 }
1255 ++t;
1256 t1 = parse_base_unresolved_name(t, last, db);
1257 if (t1 == t)
1258 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001259 if (!db.names.empty())
1260 db.names.pop_back();
Howard Hinnant6c33e762013-06-17 18:10:34 +00001261 return first;
1262 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00001263 if (db.names.size() < 2)
1264 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001265 auto s = db.names.back().move_full();
1266 db.names.pop_back();
1267 db.names.back().first += "::" + std::move(s);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001268 first = t1;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001269 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001270 }
1271 }
1272 }
1273 return first;
1274}
1275
1276// dt <expression> <unresolved-name> # expr.name
1277
Howard Hinnant6c33e762013-06-17 18:10:34 +00001278template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001279const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001280parse_dot_expr(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001281{
1282 if (last - first >= 3 && first[0] == 'd' && first[1] == 't')
1283 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001284 const char* t = parse_expression(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001285 if (t != first+2)
1286 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001287 const char* t1 = parse_unresolved_name(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001288 if (t1 != t)
1289 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001290 if (db.names.size() < 2)
1291 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001292 auto name = db.names.back().move_full();
1293 db.names.pop_back();
1294 db.names.back().first += "." + name;
1295 first = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001296 }
1297 }
1298 }
1299 return first;
1300}
1301
Howard Hinnant6c33e762013-06-17 18:10:34 +00001302// cl <expression>+ E # call
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001303
Howard Hinnant6c33e762013-06-17 18:10:34 +00001304template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001305const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001306parse_call_expr(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001307{
Howard Hinnant6c33e762013-06-17 18:10:34 +00001308 if (last - first >= 4 && first[0] == 'c' && first[1] == 'l')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001309 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001310 const char* t = parse_expression(first+2, last, db);
1311 if (t != first+2)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001312 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001313 if (t == last)
1314 return first;
Howard Hinnant753a30d2013-12-11 19:44:25 +00001315 if (db.names.empty())
1316 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001317 db.names.back().first += db.names.back().second;
1318 db.names.back().second = typename C::String();
1319 db.names.back().first.append("(");
1320 bool first_expr = true;
1321 while (*t != 'E')
1322 {
1323 const char* t1 = parse_expression(t, last, db);
1324 if (t1 == t || t1 == last)
1325 return first;
Howard Hinnant753a30d2013-12-11 19:44:25 +00001326 if (db.names.empty())
1327 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001328 auto tmp = db.names.back().move_full();
1329 db.names.pop_back();
1330 if (!tmp.empty())
1331 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001332 if (db.names.empty())
1333 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001334 if (!first_expr)
1335 {
1336 db.names.back().first.append(", ");
1337 first_expr = false;
1338 }
1339 db.names.back().first.append(tmp);
1340 }
1341 t = t1;
1342 }
1343 ++t;
Howard Hinnant753a30d2013-12-11 19:44:25 +00001344 if (db.names.empty())
1345 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001346 db.names.back().first.append(")");
1347 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001348 }
1349 }
1350 return first;
1351}
1352
1353// [gs] nw <expression>* _ <type> E # new (expr-list) type
1354// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
1355// [gs] na <expression>* _ <type> E # new[] (expr-list) type
1356// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1357// <initializer> ::= pi <expression>* E # parenthesized initialization
1358
Howard Hinnant6c33e762013-06-17 18:10:34 +00001359template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001360const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001361parse_new_expr(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001362{
1363 if (last - first >= 4)
1364 {
1365 const char* t = first;
1366 bool parsed_gs = false;
1367 if (t[0] == 'g' && t[1] == 's')
1368 {
1369 t += 2;
1370 parsed_gs = true;
1371 }
1372 if (t[0] == 'n' && (t[1] == 'w' || t[1] == 'a'))
1373 {
1374 bool is_array = t[1] == 'a';
1375 t += 2;
1376 if (t == last)
1377 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001378 bool has_expr_list = false;
1379 bool first_expr = true;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001380 while (*t != '_')
1381 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001382 const char* t1 = parse_expression(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001383 if (t1 == t || t1 == last)
1384 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001385 has_expr_list = true;
1386 if (!first_expr)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001387 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001388 if (db.names.empty())
1389 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001390 auto tmp = db.names.back().move_full();
1391 db.names.pop_back();
1392 if (!tmp.empty())
1393 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001394 if (db.names.empty())
1395 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001396 db.names.back().first.append(", ");
1397 db.names.back().first.append(tmp);
1398 first_expr = false;
1399 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001400 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001401 t = t1;
1402 }
1403 ++t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001404 const char* t1 = parse_type(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001405 if (t1 == t || t1 == last)
1406 return first;
1407 t = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001408 bool has_init = false;
1409 if (last - t >= 3 && t[0] == 'p' && t[1] == 'i')
1410 {
1411 t += 2;
1412 has_init = true;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001413 first_expr = true;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001414 while (*t != 'E')
1415 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001416 t1 = parse_expression(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001417 if (t1 == t || t1 == last)
1418 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001419 if (!first_expr)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001420 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001421 if (db.names.empty())
1422 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001423 auto tmp = db.names.back().move_full();
1424 db.names.pop_back();
1425 if (!tmp.empty())
1426 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001427 if (db.names.empty())
1428 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001429 db.names.back().first.append(", ");
1430 db.names.back().first.append(tmp);
1431 first_expr = false;
1432 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001433 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001434 t = t1;
1435 }
1436 }
1437 if (*t != 'E')
1438 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001439 typename C::String init_list;
1440 if (has_init)
1441 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001442 if (db.names.empty())
1443 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001444 init_list = db.names.back().move_full();
1445 db.names.pop_back();
1446 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00001447 if (db.names.empty())
1448 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001449 auto type = db.names.back().move_full();
1450 db.names.pop_back();
1451 typename C::String expr_list;
1452 if (has_expr_list)
1453 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001454 if (db.names.empty())
1455 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001456 expr_list = db.names.back().move_full();
1457 db.names.pop_back();
1458 }
1459 typename C::String r;
1460 if (parsed_gs)
1461 r = "::";
1462 if (is_array)
1463 r += "[] ";
1464 else
1465 r += " ";
1466 if (has_expr_list)
1467 r += "(" + expr_list + ") ";
1468 r += type;
1469 if (has_init)
1470 r += " (" + init_list + ")";
1471 db.names.push_back(std::move(r));
1472 first = t+1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001473 }
1474 }
1475 return first;
1476}
1477
Howard Hinnant6c33e762013-06-17 18:10:34 +00001478// cv <type> <expression> # conversion with one argument
1479// cv <type> _ <expression>* E # conversion with a different number of arguments
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001480
Howard Hinnant6c33e762013-06-17 18:10:34 +00001481template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001482const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001483parse_conversion_expr(const char* first, const char* last, C& db)
1484{
1485 if (last - first >= 3 && first[0] == 'c' && first[1] == 'v')
1486 {
1487 bool try_to_parse_template_args = db.try_to_parse_template_args;
1488 db.try_to_parse_template_args = false;
1489 const char* t = parse_type(first+2, last, db);
1490 db.try_to_parse_template_args = try_to_parse_template_args;
1491 if (t != first+2 && t != last)
1492 {
1493 if (*t != '_')
1494 {
1495 const char* t1 = parse_expression(t, last, db);
1496 if (t1 == t)
1497 return first;
1498 t = t1;
1499 }
1500 else
1501 {
1502 ++t;
1503 if (t == last)
1504 return first;
1505 if (*t == 'E')
1506 db.names.emplace_back();
1507 else
1508 {
1509 bool first_expr = true;
1510 while (*t != 'E')
1511 {
1512 const char* t1 = parse_expression(t, last, db);
1513 if (t1 == t || t1 == last)
1514 return first;
1515 if (!first_expr)
1516 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001517 if (db.names.empty())
1518 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001519 auto tmp = db.names.back().move_full();
1520 db.names.pop_back();
1521 if (!tmp.empty())
1522 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001523 if (db.names.empty())
1524 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001525 db.names.back().first.append(", ");
1526 db.names.back().first.append(tmp);
1527 first_expr = false;
1528 }
1529 }
1530 t = t1;
1531 }
1532 }
1533 ++t;
1534 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00001535 if (db.names.size() < 2)
1536 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001537 auto tmp = db.names.back().move_full();
1538 db.names.pop_back();
1539 db.names.back() = "(" + db.names.back().move_full() + ")(" + tmp + ")";
1540 first = t;
1541 }
1542 }
1543 return first;
1544}
1545
1546// pt <expression> <expression> # expr->name
1547
1548template <class C>
1549const char*
1550parse_arrow_expr(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001551{
1552 if (last - first >= 3 && first[0] == 'p' && first[1] == 't')
1553 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001554 const char* t = parse_expression(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001555 if (t != first+2)
1556 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001557 const char* t1 = parse_expression(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001558 if (t1 != t)
1559 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001560 if (db.names.size() < 2)
1561 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001562 auto tmp = db.names.back().move_full();
1563 db.names.pop_back();
1564 db.names.back().first += "->";
1565 db.names.back().first += tmp;
1566 first = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001567 }
1568 }
1569 }
1570 return first;
1571}
1572
Howard Hinnant6c33e762013-06-17 18:10:34 +00001573// <ref-qualifier> ::= R # & ref-qualifier
1574// <ref-qualifier> ::= O # && ref-qualifier
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001575
Howard Hinnant6c33e762013-06-17 18:10:34 +00001576// <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
1577
1578template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001579const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001580parse_function_type(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001581{
Howard Hinnant6c33e762013-06-17 18:10:34 +00001582 if (first != last && *first == 'F')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001583 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001584 const char* t = first+1;
1585 if (t != last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001586 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001587 if (*t == 'Y')
1588 {
Saleem Abdulrasoolb2cceca2015-04-27 02:21:57 +00001589 /* extern "C" */
Howard Hinnant6c33e762013-06-17 18:10:34 +00001590 if (++t == last)
1591 return first;
1592 }
1593 const char* t1 = parse_type(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001594 if (t1 != t)
1595 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001596 t = t1;
1597 typename C::String sig("(");
1598 int ref_qual = 0;
1599 while (true)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001600 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001601 if (t == last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001602 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001603 db.names.pop_back();
1604 return first;
1605 }
1606 if (*t == 'E')
1607 {
1608 ++t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001609 break;
1610 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001611 if (*t == 'v')
1612 {
1613 ++t;
1614 continue;
1615 }
1616 if (*t == 'R' && t+1 != last && t[1] == 'E')
1617 {
1618 ref_qual = 1;
1619 ++t;
1620 continue;
1621 }
1622 if (*t == 'O' && t+1 != last && t[1] == 'E')
1623 {
1624 ref_qual = 2;
1625 ++t;
1626 continue;
1627 }
1628 size_t k0 = db.names.size();
1629 t1 = parse_type(t, last, db);
1630 size_t k1 = db.names.size();
1631 if (t1 == t || t1 == last)
1632 return first;
1633 for (size_t k = k0; k < k1; ++k)
1634 {
1635 if (sig.size() > 1)
1636 sig += ", ";
1637 sig += db.names[k].move_full();
1638 }
1639 for (size_t k = k0; k < k1; ++k)
1640 db.names.pop_back();
1641 t = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001642 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001643 sig += ")";
1644 switch (ref_qual)
1645 {
1646 case 1:
1647 sig += " &";
1648 break;
1649 case 2:
1650 sig += " &&";
1651 break;
1652 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00001653 if (db.names.empty())
1654 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001655 db.names.back().first += " ";
1656 db.names.back().second.insert(0, sig);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001657 first = t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001658 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001659 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001660 }
1661 return first;
1662}
1663
1664// <pointer-to-member-type> ::= M <class type> <member type>
1665
1666template <class C>
1667const char*
1668parse_pointer_to_member_type(const char* first, const char* last, C& db)
1669{
1670 if (first != last && *first == 'M')
1671 {
1672 const char* t = parse_type(first+1, last, db);
1673 if (t != first+1)
1674 {
1675 const char* t2 = parse_type(t, last, db);
1676 if (t2 != t)
1677 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001678 if (db.names.size() < 2)
1679 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001680 auto func = std::move(db.names.back());
1681 db.names.pop_back();
1682 auto class_type = std::move(db.names.back());
Chaoren Lin3b8762a2015-05-26 23:14:26 +00001683 if (!func.second.empty() && func.second.front() == '(')
Howard Hinnant6c33e762013-06-17 18:10:34 +00001684 {
1685 db.names.back().first = std::move(func.first) + "(" + class_type.move_full() + "::*";
1686 db.names.back().second = ")" + std::move(func.second);
1687 }
1688 else
1689 {
1690 db.names.back().first = std::move(func.first) + " " + class_type.move_full() + "::*";
1691 db.names.back().second = std::move(func.second);
1692 }
1693 first = t2;
1694 }
1695 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001696 }
1697 return first;
1698}
1699
1700// <array-type> ::= A <positive dimension number> _ <element type>
1701// ::= A [<dimension expression>] _ <element type>
1702
Howard Hinnant6c33e762013-06-17 18:10:34 +00001703template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001704const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001705parse_array_type(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001706{
1707 if (first != last && *first == 'A' && first+1 != last)
1708 {
1709 if (first[1] == '_')
1710 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001711 const char* t = parse_type(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001712 if (t != first+2)
1713 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001714 if (db.names.empty())
1715 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001716 if (db.names.back().second.substr(0, 2) == " [")
1717 db.names.back().second.erase(0, 1);
1718 db.names.back().second.insert(0, " []");
1719 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001720 }
1721 }
1722 else if ('1' <= first[1] && first[1] <= '9')
1723 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001724 const char* t = parse_number(first+1, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001725 if (t != last && *t == '_')
1726 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001727 const char* t2 = parse_type(t+1, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001728 if (t2 != t+1)
1729 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001730 if (db.names.empty())
1731 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001732 if (db.names.back().second.substr(0, 2) == " [")
1733 db.names.back().second.erase(0, 1);
1734 db.names.back().second.insert(0, " [" + typename C::String(first+1, t) + "]");
1735 first = t2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001736 }
1737 }
1738 }
1739 else
1740 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001741 const char* t = parse_expression(first+1, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001742 if (t != first+1 && t != last && *t == '_')
1743 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001744 const char* t2 = parse_type(++t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001745 if (t2 != t)
1746 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001747 if (db.names.size() < 2)
1748 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001749 auto type = std::move(db.names.back());
1750 db.names.pop_back();
1751 auto expr = std::move(db.names.back());
1752 db.names.back().first = std::move(type.first);
1753 if (type.second.substr(0, 2) == " [")
1754 type.second.erase(0, 1);
1755 db.names.back().second = " [" + expr.move_full() + "]" + std::move(type.second);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001756 first = t2;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001757 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001758 }
1759 }
1760 }
1761 return first;
1762}
1763
1764// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
1765// ::= DT <expression> E # decltype of an expression (C++0x)
1766
Howard Hinnant6c33e762013-06-17 18:10:34 +00001767template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001768const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001769parse_decltype(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001770{
1771 if (last - first >= 4 && first[0] == 'D')
1772 {
1773 switch (first[1])
1774 {
1775 case 't':
1776 case 'T':
1777 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001778 const char* t = parse_expression(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001779 if (t != first+2 && t != last && *t == 'E')
1780 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001781 if (db.names.empty())
1782 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001783 db.names.back() = "decltype(" + db.names.back().move_full() + ")";
1784 first = t+1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001785 }
1786 }
1787 break;
1788 }
1789 }
1790 return first;
1791}
1792
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001793// extension:
1794// <vector-type> ::= Dv <positive dimension number> _
1795// <extended element type>
1796// ::= Dv [<dimension expression>] _ <element type>
1797// <extended element type> ::= <element type>
1798// ::= p # AltiVec vector pixel
1799
Howard Hinnant6c33e762013-06-17 18:10:34 +00001800template <class C>
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001801const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001802parse_vector_type(const char* first, const char* last, C& db)
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001803{
1804 if (last - first > 3 && first[0] == 'D' && first[1] == 'v')
1805 {
1806 if ('1' <= first[2] && first[2] <= '9')
1807 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001808 const char* t = parse_number(first+2, last);
1809 if (t == last || *t != '_')
1810 return first;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001811 const char* num = first + 2;
Howard Hinnant3e5c7d02012-03-08 18:45:24 +00001812 size_t sz = static_cast<size_t>(t - num);
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001813 if (++t != last)
1814 {
1815 if (*t != 'p')
1816 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001817 const char* t1 = parse_type(t, last, db);
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001818 if (t1 != t)
1819 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001820 if (db.names.empty())
1821 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001822 db.names.back().first += " vector[" + typename C::String(num, sz) + "]";
1823 first = t1;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001824 }
1825 }
1826 else
1827 {
1828 ++t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001829 db.names.push_back("pixel vector[" + typename C::String(num, sz) + "]");
1830 first = t;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001831 }
1832 }
1833 }
1834 else
1835 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001836 typename C::String num;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001837 const char* t1 = first+2;
1838 if (*t1 != '_')
1839 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001840 const char* t = parse_expression(t1, last, db);
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001841 if (t != t1)
Howard Hinnant6c33e762013-06-17 18:10:34 +00001842 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001843 if (db.names.empty())
1844 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001845 num = db.names.back().move_full();
1846 db.names.pop_back();
1847 t1 = t;
1848 }
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001849 }
1850 if (t1 != last && *t1 == '_' && ++t1 != last)
1851 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001852 const char* t = parse_type(t1, last, db);
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001853 if (t != t1)
1854 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001855 if (db.names.empty())
1856 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001857 db.names.back().first += " vector[" + num + "]";
1858 first = t;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001859 }
1860 }
1861 }
1862 }
1863 return first;
1864}
1865
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001866// <type> ::= <builtin-type>
1867// ::= <function-type>
1868// ::= <class-enum-type>
1869// ::= <array-type>
1870// ::= <pointer-to-member-type>
1871// ::= <template-param>
1872// ::= <template-template-param> <template-args>
1873// ::= <decltype>
1874// ::= <substitution>
1875// ::= <CV-qualifiers> <type>
1876// ::= P <type> # pointer-to
1877// ::= R <type> # reference-to
1878// ::= O <type> # rvalue reference-to (C++0x)
1879// ::= C <type> # complex pair (C 2000)
1880// ::= G <type> # imaginary (C 2000)
1881// ::= Dp <type> # pack expansion (C++0x)
1882// ::= U <source-name> <type> # vendor extended type qualifier
Howard Hinnant19e36dd2013-06-19 13:43:18 +00001883// extension := U <objc-name> <objc-type> # objc-type<identifier>
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001884// extension := <vector-type> # <vector-type> starts with Dv
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001885
Howard Hinnant19e36dd2013-06-19 13:43:18 +00001886// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
1887// <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
1888
Howard Hinnant6c33e762013-06-17 18:10:34 +00001889template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001890const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001891parse_type(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001892{
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001893 if (first != last)
1894 {
1895 switch (*first)
1896 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001897 case 'r':
1898 case 'V':
1899 case 'K':
1900 {
1901 unsigned cv = 0;
1902 const char* t = parse_cv_qualifiers(first, last, cv);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001903 if (t != first)
1904 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001905 bool is_function = *t == 'F';
1906 size_t k0 = db.names.size();
1907 const char* t1 = parse_type(t, last, db);
1908 size_t k1 = db.names.size();
1909 if (t1 != t)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001910 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001911 if (is_function)
1912 db.subs.pop_back();
1913 db.subs.emplace_back(db.names.get_allocator());
1914 for (size_t k = k0; k < k1; ++k)
1915 {
1916 if (is_function)
1917 {
1918 size_t p = db.names[k].second.size();
1919 if (db.names[k].second[p-2] == '&')
1920 p -= 3;
1921 else if (db.names[k].second.back() == '&')
1922 p -= 2;
1923 if (cv & 1)
1924 {
1925 db.names[k].second.insert(p, " const");
1926 p += 6;
1927 }
1928 if (cv & 2)
1929 {
1930 db.names[k].second.insert(p, " volatile");
1931 p += 9;
1932 }
1933 if (cv & 4)
1934 db.names[k].second.insert(p, " restrict");
1935 }
1936 else
1937 {
1938 if (cv & 1)
1939 db.names[k].first.append(" const");
1940 if (cv & 2)
1941 db.names[k].first.append(" volatile");
1942 if (cv & 4)
1943 db.names[k].first.append(" restrict");
1944 }
1945 db.subs.back().push_back(db.names[k]);
1946 }
1947 first = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001948 }
1949 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001950 }
1951 break;
1952 default:
1953 {
1954 const char* t = parse_builtin_type(first, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001955 if (t != first)
1956 {
1957 first = t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001958 }
1959 else
1960 {
1961 switch (*first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001962 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001963 case 'A':
1964 t = parse_array_type(first, last, db);
1965 if (t != first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001966 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001967 if (db.names.empty())
1968 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001969 first = t;
1970 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
1971 }
1972 break;
1973 case 'C':
1974 t = parse_type(first+1, last, db);
1975 if (t != first+1)
1976 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001977 if (db.names.empty())
1978 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001979 db.names.back().first.append(" complex");
1980 first = t;
1981 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
1982 }
1983 break;
1984 case 'F':
1985 t = parse_function_type(first, last, db);
1986 if (t != first)
1987 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001988 if (db.names.empty())
1989 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001990 first = t;
1991 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
1992 }
1993 break;
1994 case 'G':
1995 t = parse_type(first+1, last, db);
1996 if (t != first+1)
1997 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001998 if (db.names.empty())
1999 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002000 db.names.back().first.append(" imaginary");
2001 first = t;
2002 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2003 }
2004 break;
2005 case 'M':
2006 t = parse_pointer_to_member_type(first, last, db);
2007 if (t != first)
2008 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002009 if (db.names.empty())
2010 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002011 first = t;
2012 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2013 }
2014 break;
2015 case 'O':
2016 {
2017 size_t k0 = db.names.size();
2018 t = parse_type(first+1, last, db);
2019 size_t k1 = db.names.size();
2020 if (t != first+1)
2021 {
2022 db.subs.emplace_back(db.names.get_allocator());
2023 for (size_t k = k0; k < k1; ++k)
2024 {
2025 if (db.names[k].second.substr(0, 2) == " [")
2026 {
2027 db.names[k].first += " (";
2028 db.names[k].second.insert(0, ")");
2029 }
Chaoren Lin3b8762a2015-05-26 23:14:26 +00002030 else if (!db.names[k].second.empty() &&
2031 db.names[k].second.front() == '(')
Howard Hinnant6c33e762013-06-17 18:10:34 +00002032 {
2033 db.names[k].first += "(";
2034 db.names[k].second.insert(0, ")");
2035 }
2036 db.names[k].first.append("&&");
2037 db.subs.back().push_back(db.names[k]);
2038 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002039 first = t;
2040 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002041 break;
2042 }
2043 case 'P':
2044 {
2045 size_t k0 = db.names.size();
2046 t = parse_type(first+1, last, db);
2047 size_t k1 = db.names.size();
2048 if (t != first+1)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002049 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002050 db.subs.emplace_back(db.names.get_allocator());
2051 for (size_t k = k0; k < k1; ++k)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002052 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002053 if (db.names[k].second.substr(0, 2) == " [")
2054 {
2055 db.names[k].first += " (";
2056 db.names[k].second.insert(0, ")");
2057 }
Chaoren Lin3b8762a2015-05-26 23:14:26 +00002058 else if (!db.names[k].second.empty() &&
2059 db.names[k].second.front() == '(')
Howard Hinnant6c33e762013-06-17 18:10:34 +00002060 {
2061 db.names[k].first += "(";
2062 db.names[k].second.insert(0, ")");
2063 }
Howard Hinnant19e36dd2013-06-19 13:43:18 +00002064 if (first[1] != 'U' || db.names[k].first.substr(0, 12) != "objc_object<")
2065 {
2066 db.names[k].first.append("*");
2067 }
2068 else
2069 {
2070 db.names[k].first.replace(0, 11, "id");
2071 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002072 db.subs.back().push_back(db.names[k]);
2073 }
2074 first = t;
2075 }
2076 break;
2077 }
2078 case 'R':
2079 {
2080 size_t k0 = db.names.size();
2081 t = parse_type(first+1, last, db);
2082 size_t k1 = db.names.size();
2083 if (t != first+1)
2084 {
2085 db.subs.emplace_back(db.names.get_allocator());
2086 for (size_t k = k0; k < k1; ++k)
2087 {
2088 if (db.names[k].second.substr(0, 2) == " [")
2089 {
2090 db.names[k].first += " (";
2091 db.names[k].second.insert(0, ")");
2092 }
Chaoren Lin3b8762a2015-05-26 23:14:26 +00002093 else if (!db.names[k].second.empty() &&
2094 db.names[k].second.front() == '(')
Howard Hinnant6c33e762013-06-17 18:10:34 +00002095 {
2096 db.names[k].first += "(";
2097 db.names[k].second.insert(0, ")");
2098 }
2099 db.names[k].first.append("&");
2100 db.subs.back().push_back(db.names[k]);
2101 }
2102 first = t;
2103 }
2104 break;
2105 }
2106 case 'T':
2107 {
2108 size_t k0 = db.names.size();
2109 t = parse_template_param(first, last, db);
2110 size_t k1 = db.names.size();
2111 if (t != first)
2112 {
2113 db.subs.emplace_back(db.names.get_allocator());
2114 for (size_t k = k0; k < k1; ++k)
2115 db.subs.back().push_back(db.names[k]);
2116 if (db.try_to_parse_template_args && k1 == k0+1)
2117 {
2118 const char* t1 = parse_template_args(t, last, db);
2119 if (t1 != t)
2120 {
2121 auto args = db.names.back().move_full();
2122 db.names.pop_back();
2123 db.names.back().first += std::move(args);
2124 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2125 t = t1;
2126 }
2127 }
2128 first = t;
2129 }
2130 break;
2131 }
2132 case 'U':
2133 if (first+1 != last)
2134 {
2135 t = parse_source_name(first+1, last, db);
2136 if (t != first+1)
2137 {
2138 const char* t2 = parse_type(t, last, db);
2139 if (t2 != t)
2140 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002141 if (db.names.size() < 2)
2142 return first;
Howard Hinnant19e36dd2013-06-19 13:43:18 +00002143 auto type = db.names.back().move_full();
Howard Hinnant6c33e762013-06-17 18:10:34 +00002144 db.names.pop_back();
Howard Hinnant19e36dd2013-06-19 13:43:18 +00002145 if (db.names.back().first.substr(0, 9) != "objcproto")
2146 {
2147 db.names.back() = type + " " + db.names.back().move_full();
2148 }
2149 else
2150 {
2151 auto proto = db.names.back().move_full();
2152 db.names.pop_back();
2153 t = parse_source_name(proto.data() + 9, proto.data() + proto.size(), db);
2154 if (t != proto.data() + 9)
2155 {
2156 db.names.back() = type + "<" + db.names.back().move_full() + ">";
2157 }
2158 else
2159 {
2160 db.names.push_back(type + " " + proto);
2161 }
2162 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002163 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2164 first = t2;
2165 }
2166 }
2167 }
2168 break;
2169 case 'S':
2170 if (first+1 != last && first[1] == 't')
2171 {
2172 t = parse_name(first, last, db);
2173 if (t != first)
2174 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002175 if (db.names.empty())
2176 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002177 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002178 first = t;
2179 }
2180 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002181 else
2182 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002183 t = parse_substitution(first, last, db);
2184 if (t != first)
2185 {
2186 first = t;
2187 // Parsed a substitution. If the substitution is a
2188 // <template-param> it might be followed by <template-args>.
2189 t = parse_template_args(first, last, db);
2190 if (t != first)
2191 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002192 if (db.names.size() < 2)
2193 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002194 auto template_args = db.names.back().move_full();
2195 db.names.pop_back();
2196 db.names.back().first += template_args;
2197 // Need to create substitution for <template-template-param> <template-args>
2198 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2199 first = t;
2200 }
2201 }
2202 }
2203 break;
2204 case 'D':
2205 if (first+1 != last)
2206 {
2207 switch (first[1])
2208 {
2209 case 'p':
2210 {
2211 size_t k0 = db.names.size();
2212 t = parse_type(first+2, last, db);
2213 size_t k1 = db.names.size();
Howard Hinnantf6725172013-06-21 17:04:24 +00002214 if (t != first+2)
Howard Hinnant6c33e762013-06-17 18:10:34 +00002215 {
2216 db.subs.emplace_back(db.names.get_allocator());
2217 for (size_t k = k0; k < k1; ++k)
2218 db.subs.back().push_back(db.names[k]);
2219 first = t;
2220 return first;
2221 }
2222 break;
2223 }
2224 case 't':
2225 case 'T':
2226 t = parse_decltype(first, last, db);
2227 if (t != first)
2228 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002229 if (db.names.empty())
2230 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002231 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2232 first = t;
2233 return first;
2234 }
2235 break;
2236 case 'v':
2237 t = parse_vector_type(first, last, db);
2238 if (t != first)
2239 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002240 if (db.names.empty())
2241 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002242 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2243 first = t;
2244 return first;
2245 }
2246 break;
2247 }
2248 }
2249 // drop through
2250 default:
2251 // must check for builtin-types before class-enum-types to avoid
2252 // ambiguities with operator-names
2253 t = parse_builtin_type(first, last, db);
2254 if (t != first)
2255 {
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002256 first = t;
2257 }
Howard Hinnantab87dcf2011-12-15 20:02:15 +00002258 else
2259 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002260 t = parse_name(first, last, db);
2261 if (t != first)
2262 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002263 if (db.names.empty())
2264 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002265 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2266 first = t;
2267 }
Howard Hinnantab87dcf2011-12-15 20:02:15 +00002268 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002269 break;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00002270 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002271 }
2272 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002273 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002274 }
2275 }
2276 return first;
2277}
2278
2279// <operator-name>
2280// ::= aa # &&
2281// ::= ad # & (unary)
2282// ::= an # &
2283// ::= aN # &=
2284// ::= aS # =
2285// ::= cl # ()
2286// ::= cm # ,
2287// ::= co # ~
2288// ::= cv <type> # (cast)
2289// ::= da # delete[]
2290// ::= de # * (unary)
2291// ::= dl # delete
2292// ::= dv # /
2293// ::= dV # /=
2294// ::= eo # ^
2295// ::= eO # ^=
2296// ::= eq # ==
2297// ::= ge # >=
2298// ::= gt # >
2299// ::= ix # []
2300// ::= le # <=
Howard Hinnantf29757a2014-01-06 23:05:04 +00002301// ::= li <source-name> # operator ""
Howard Hinnant6c33e762013-06-17 18:10:34 +00002302// ::= ls # <<
2303// ::= lS # <<=
2304// ::= lt # <
2305// ::= mi # -
2306// ::= mI # -=
2307// ::= ml # *
2308// ::= mL # *=
2309// ::= mm # -- (postfix in <expression> context)
2310// ::= na # new[]
2311// ::= ne # !=
2312// ::= ng # - (unary)
2313// ::= nt # !
2314// ::= nw # new
2315// ::= oo # ||
2316// ::= or # |
2317// ::= oR # |=
2318// ::= pm # ->*
2319// ::= pl # +
2320// ::= pL # +=
2321// ::= pp # ++ (postfix in <expression> context)
2322// ::= ps # + (unary)
2323// ::= pt # ->
2324// ::= qu # ?
2325// ::= rm # %
2326// ::= rM # %=
2327// ::= rs # >>
2328// ::= rS # >>=
2329// ::= v <digit> <source-name> # vendor extended operator
2330
2331template <class C>
2332const char*
2333parse_operator_name(const char* first, const char* last, C& db)
2334{
2335 if (last - first >= 2)
2336 {
2337 switch (first[0])
2338 {
2339 case 'a':
2340 switch (first[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002341 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002342 case 'a':
2343 db.names.push_back("operator&&");
2344 first += 2;
2345 break;
2346 case 'd':
2347 case 'n':
2348 db.names.push_back("operator&");
2349 first += 2;
2350 break;
2351 case 'N':
2352 db.names.push_back("operator&=");
2353 first += 2;
2354 break;
2355 case 'S':
2356 db.names.push_back("operator=");
2357 first += 2;
2358 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002359 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002360 break;
2361 case 'c':
2362 switch (first[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002363 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002364 case 'l':
2365 db.names.push_back("operator()");
2366 first += 2;
2367 break;
2368 case 'm':
2369 db.names.push_back("operator,");
2370 first += 2;
2371 break;
2372 case 'o':
2373 db.names.push_back("operator~");
2374 first += 2;
2375 break;
2376 case 'v':
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002377 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002378 bool try_to_parse_template_args = db.try_to_parse_template_args;
2379 db.try_to_parse_template_args = false;
2380 const char* t = parse_type(first+2, last, db);
2381 db.try_to_parse_template_args = try_to_parse_template_args;
2382 if (t != first+2)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002383 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002384 if (db.names.empty())
2385 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002386 db.names.back().first.insert(0, "operator ");
2387 db.parsed_ctor_dtor_cv = true;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002388 first = t;
2389 }
2390 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002391 break;
2392 }
2393 break;
2394 case 'd':
2395 switch (first[1])
2396 {
2397 case 'a':
2398 db.names.push_back("operator delete[]");
2399 first += 2;
2400 break;
2401 case 'e':
2402 db.names.push_back("operator*");
2403 first += 2;
2404 break;
2405 case 'l':
2406 db.names.push_back("operator delete");
2407 first += 2;
2408 break;
2409 case 'v':
2410 db.names.push_back("operator/");
2411 first += 2;
2412 break;
2413 case 'V':
2414 db.names.push_back("operator/=");
2415 first += 2;
2416 break;
2417 }
2418 break;
2419 case 'e':
2420 switch (first[1])
2421 {
2422 case 'o':
2423 db.names.push_back("operator^");
2424 first += 2;
2425 break;
2426 case 'O':
2427 db.names.push_back("operator^=");
2428 first += 2;
2429 break;
2430 case 'q':
2431 db.names.push_back("operator==");
2432 first += 2;
2433 break;
2434 }
2435 break;
2436 case 'g':
2437 switch (first[1])
2438 {
2439 case 'e':
2440 db.names.push_back("operator>=");
2441 first += 2;
2442 break;
2443 case 't':
2444 db.names.push_back("operator>");
2445 first += 2;
2446 break;
2447 }
2448 break;
2449 case 'i':
2450 if (first[1] == 'x')
2451 {
2452 db.names.push_back("operator[]");
2453 first += 2;
2454 }
2455 break;
2456 case 'l':
2457 switch (first[1])
2458 {
2459 case 'e':
2460 db.names.push_back("operator<=");
2461 first += 2;
2462 break;
Howard Hinnantf29757a2014-01-06 23:05:04 +00002463 case 'i':
2464 {
2465 const char* t = parse_source_name(first+2, last, db);
2466 if (t != first+2)
2467 {
2468 if (db.names.empty())
2469 return first;
2470 db.names.back().first.insert(0, "operator\"\" ");
2471 first = t;
2472 }
2473 }
2474 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002475 case 's':
2476 db.names.push_back("operator<<");
2477 first += 2;
2478 break;
2479 case 'S':
2480 db.names.push_back("operator<<=");
2481 first += 2;
2482 break;
2483 case 't':
2484 db.names.push_back("operator<");
2485 first += 2;
2486 break;
2487 }
2488 break;
2489 case 'm':
2490 switch (first[1])
2491 {
2492 case 'i':
2493 db.names.push_back("operator-");
2494 first += 2;
2495 break;
2496 case 'I':
2497 db.names.push_back("operator-=");
2498 first += 2;
2499 break;
2500 case 'l':
2501 db.names.push_back("operator*");
2502 first += 2;
2503 break;
2504 case 'L':
2505 db.names.push_back("operator*=");
2506 first += 2;
2507 break;
2508 case 'm':
2509 db.names.push_back("operator--");
2510 first += 2;
2511 break;
2512 }
2513 break;
2514 case 'n':
2515 switch (first[1])
2516 {
2517 case 'a':
2518 db.names.push_back("operator new[]");
2519 first += 2;
2520 break;
2521 case 'e':
2522 db.names.push_back("operator!=");
2523 first += 2;
2524 break;
2525 case 'g':
2526 db.names.push_back("operator-");
2527 first += 2;
2528 break;
2529 case 't':
2530 db.names.push_back("operator!");
2531 first += 2;
2532 break;
2533 case 'w':
2534 db.names.push_back("operator new");
2535 first += 2;
2536 break;
2537 }
2538 break;
2539 case 'o':
2540 switch (first[1])
2541 {
2542 case 'o':
2543 db.names.push_back("operator||");
2544 first += 2;
2545 break;
2546 case 'r':
2547 db.names.push_back("operator|");
2548 first += 2;
2549 break;
2550 case 'R':
2551 db.names.push_back("operator|=");
2552 first += 2;
2553 break;
2554 }
2555 break;
2556 case 'p':
2557 switch (first[1])
2558 {
2559 case 'm':
2560 db.names.push_back("operator->*");
2561 first += 2;
2562 break;
2563 case 'l':
2564 db.names.push_back("operator+");
2565 first += 2;
2566 break;
2567 case 'L':
2568 db.names.push_back("operator+=");
2569 first += 2;
2570 break;
2571 case 'p':
2572 db.names.push_back("operator++");
2573 first += 2;
2574 break;
2575 case 's':
2576 db.names.push_back("operator+");
2577 first += 2;
2578 break;
2579 case 't':
2580 db.names.push_back("operator->");
2581 first += 2;
2582 break;
2583 }
2584 break;
2585 case 'q':
2586 if (first[1] == 'u')
2587 {
2588 db.names.push_back("operator?");
2589 first += 2;
2590 }
2591 break;
2592 case 'r':
2593 switch (first[1])
2594 {
2595 case 'm':
2596 db.names.push_back("operator%");
2597 first += 2;
2598 break;
2599 case 'M':
2600 db.names.push_back("operator%=");
2601 first += 2;
2602 break;
2603 case 's':
2604 db.names.push_back("operator>>");
2605 first += 2;
2606 break;
2607 case 'S':
2608 db.names.push_back("operator>>=");
2609 first += 2;
2610 break;
2611 }
2612 break;
2613 case 'v':
2614 if (std::isdigit(first[1]))
2615 {
2616 const char* t = parse_source_name(first+2, last, db);
2617 if (t != first+2)
2618 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002619 if (db.names.empty())
2620 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002621 db.names.back().first.insert(0, "operator ");
2622 first = t;
2623 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002624 }
2625 break;
2626 }
2627 }
2628 return first;
2629}
2630
Howard Hinnant6c33e762013-06-17 18:10:34 +00002631template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002632const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00002633parse_integer_literal(const char* first, const char* last, const typename C::String& lit, C& db)
2634{
2635 const char* t = parse_number(first, last);
2636 if (t != first && t != last && *t == 'E')
2637 {
2638 if (lit.size() > 3)
2639 db.names.push_back("(" + lit + ")");
2640 else
2641 db.names.emplace_back();
2642 if (*first == 'n')
2643 {
2644 db.names.back().first += '-';
2645 ++first;
2646 }
2647 db.names.back().first.append(first, t);
2648 if (lit.size() <= 3)
2649 db.names.back().first += lit;
2650 first = t+1;
2651 }
2652 return first;
2653}
2654
2655// <expr-primary> ::= L <type> <value number> E # integer literal
2656// ::= L <type> <value float> E # floating literal
2657// ::= L <string type> E # string literal
2658// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
2659// ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
2660// ::= L <mangled-name> E # external name
2661
2662template <class C>
2663const char*
2664parse_expr_primary(const char* first, const char* last, C& db)
2665{
2666 if (last - first >= 4 && *first == 'L')
2667 {
2668 switch (first[1])
2669 {
2670 case 'w':
Howard Hinnant93433df2013-06-20 21:49:34 +00002671 {
2672 const char* t = parse_integer_literal(first+2, last, "wchar_t", db);
2673 if (t != first+2)
2674 first = t;
2675 }
2676 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002677 case 'b':
2678 if (first[3] == 'E')
2679 {
2680 switch (first[2])
2681 {
2682 case '0':
2683 db.names.push_back("false");
2684 first += 4;
2685 break;
2686 case '1':
2687 db.names.push_back("true");
2688 first += 4;
2689 break;
2690 }
2691 }
2692 break;
2693 case 'c':
Howard Hinnant93433df2013-06-20 21:49:34 +00002694 {
2695 const char* t = parse_integer_literal(first+2, last, "char", db);
2696 if (t != first+2)
2697 first = t;
2698 }
2699 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002700 case 'a':
Howard Hinnant93433df2013-06-20 21:49:34 +00002701 {
2702 const char* t = parse_integer_literal(first+2, last, "signed char", db);
2703 if (t != first+2)
2704 first = t;
2705 }
2706 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002707 case 'h':
Howard Hinnant93433df2013-06-20 21:49:34 +00002708 {
2709 const char* t = parse_integer_literal(first+2, last, "unsigned char", db);
2710 if (t != first+2)
2711 first = t;
2712 }
2713 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002714 case 's':
Howard Hinnant93433df2013-06-20 21:49:34 +00002715 {
2716 const char* t = parse_integer_literal(first+2, last, "short", db);
2717 if (t != first+2)
2718 first = t;
2719 }
2720 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002721 case 't':
Howard Hinnant93433df2013-06-20 21:49:34 +00002722 {
2723 const char* t = parse_integer_literal(first+2, last, "unsigned short", db);
2724 if (t != first+2)
2725 first = t;
2726 }
2727 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002728 case 'i':
Howard Hinnant93433df2013-06-20 21:49:34 +00002729 {
2730 const char* t = parse_integer_literal(first+2, last, "", db);
2731 if (t != first+2)
2732 first = t;
2733 }
2734 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002735 case 'j':
Howard Hinnant93433df2013-06-20 21:49:34 +00002736 {
2737 const char* t = parse_integer_literal(first+2, last, "u", db);
2738 if (t != first+2)
2739 first = t;
2740 }
2741 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002742 case 'l':
Howard Hinnant93433df2013-06-20 21:49:34 +00002743 {
2744 const char* t = parse_integer_literal(first+2, last, "l", db);
2745 if (t != first+2)
2746 first = t;
2747 }
2748 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002749 case 'm':
Howard Hinnant93433df2013-06-20 21:49:34 +00002750 {
2751 const char* t = parse_integer_literal(first+2, last, "ul", db);
2752 if (t != first+2)
2753 first = t;
2754 }
2755 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002756 case 'x':
Howard Hinnant93433df2013-06-20 21:49:34 +00002757 {
2758 const char* t = parse_integer_literal(first+2, last, "ll", db);
2759 if (t != first+2)
2760 first = t;
2761 }
2762 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002763 case 'y':
Howard Hinnant93433df2013-06-20 21:49:34 +00002764 {
2765 const char* t = parse_integer_literal(first+2, last, "ull", db);
2766 if (t != first+2)
2767 first = t;
2768 }
2769 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002770 case 'n':
Howard Hinnant93433df2013-06-20 21:49:34 +00002771 {
2772 const char* t = parse_integer_literal(first+2, last, "__int128", db);
2773 if (t != first+2)
2774 first = t;
2775 }
2776 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002777 case 'o':
Howard Hinnant93433df2013-06-20 21:49:34 +00002778 {
2779 const char* t = parse_integer_literal(first+2, last, "unsigned __int128", db);
2780 if (t != first+2)
2781 first = t;
2782 }
2783 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002784 case 'f':
Howard Hinnant93433df2013-06-20 21:49:34 +00002785 {
2786 const char* t = parse_floating_number<float>(first+2, last, db);
2787 if (t != first+2)
2788 first = t;
2789 }
2790 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002791 case 'd':
Howard Hinnant93433df2013-06-20 21:49:34 +00002792 {
2793 const char* t = parse_floating_number<double>(first+2, last, db);
2794 if (t != first+2)
2795 first = t;
2796 }
2797 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002798 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00002799 {
2800 const char* t = parse_floating_number<long double>(first+2, last, db);
2801 if (t != first+2)
2802 first = t;
2803 }
2804 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002805 case '_':
2806 if (first[2] == 'Z')
2807 {
2808 const char* t = parse_encoding(first+3, last, db);
2809 if (t != first+3 && t != last && *t == 'E')
2810 first = t+1;
2811 }
2812 break;
2813 case 'T':
2814 // Invalid mangled name per
2815 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
2816 break;
2817 default:
2818 {
2819 // might be named type
2820 const char* t = parse_type(first+1, last, db);
2821 if (t != first+1 && t != last)
2822 {
2823 if (*t != 'E')
2824 {
2825 const char* n = t;
2826 for (; n != last && isdigit(*n); ++n)
2827 ;
2828 if (n != t && n != last && *n == 'E')
2829 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002830 if (db.names.empty())
2831 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002832 db.names.back() = "(" + db.names.back().move_full() + ")" + typename C::String(t, n);
2833 first = n+1;
2834 break;
2835 }
2836 }
2837 else
2838 {
2839 first = t+1;
2840 break;
2841 }
2842 }
2843 }
2844 }
2845 }
2846 return first;
2847}
2848
2849template <class String>
2850String
2851base_name(String& s)
2852{
2853 if (s.empty())
2854 return s;
2855 if (s == "std::string")
2856 {
2857 s = "std::basic_string<char, std::char_traits<char>, std::allocator<char> >";
2858 return "basic_string";
2859 }
2860 if (s == "std::istream")
2861 {
2862 s = "std::basic_istream<char, std::char_traits<char> >";
2863 return "basic_istream";
2864 }
2865 if (s == "std::ostream")
2866 {
2867 s = "std::basic_ostream<char, std::char_traits<char> >";
2868 return "basic_ostream";
2869 }
2870 if (s == "std::iostream")
2871 {
2872 s = "std::basic_iostream<char, std::char_traits<char> >";
2873 return "basic_iostream";
2874 }
2875 const char* const pf = s.data();
2876 const char* pe = pf + s.size();
2877 if (pe[-1] == '>')
2878 {
2879 unsigned c = 1;
2880 while (true)
2881 {
2882 if (--pe == pf)
2883 return String();
2884 if (pe[-1] == '<')
2885 {
2886 if (--c == 0)
2887 {
2888 --pe;
2889 break;
2890 }
2891 }
2892 else if (pe[-1] == '>')
2893 ++c;
2894 }
2895 }
2896 const char* p0 = pe - 1;
2897 for (; p0 != pf; --p0)
2898 {
2899 if (*p0 == ':')
2900 {
2901 ++p0;
2902 break;
2903 }
2904 }
2905 return String(p0, pe);
2906}
2907
2908// <ctor-dtor-name> ::= C1 # complete object constructor
2909// ::= C2 # base object constructor
2910// ::= C3 # complete object allocating constructor
2911// extension ::= C5 # ?
2912// ::= D0 # deleting destructor
2913// ::= D1 # complete object destructor
2914// ::= D2 # base object destructor
2915// extension ::= D5 # ?
2916
2917template <class C>
2918const char*
2919parse_ctor_dtor_name(const char* first, const char* last, C& db)
2920{
2921 if (last-first >= 2 && !db.names.empty())
2922 {
2923 switch (first[0])
2924 {
2925 case 'C':
2926 switch (first[1])
2927 {
2928 case '1':
2929 case '2':
2930 case '3':
2931 case '5':
Howard Hinnant753a30d2013-12-11 19:44:25 +00002932 if (db.names.empty())
2933 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002934 db.names.push_back(base_name(db.names.back().first));
2935 first += 2;
2936 db.parsed_ctor_dtor_cv = true;
2937 break;
2938 }
2939 break;
2940 case 'D':
2941 switch (first[1])
2942 {
2943 case '0':
2944 case '1':
2945 case '2':
2946 case '5':
Howard Hinnant753a30d2013-12-11 19:44:25 +00002947 if (db.names.empty())
2948 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002949 db.names.push_back("~" + base_name(db.names.back().first));
2950 first += 2;
2951 db.parsed_ctor_dtor_cv = true;
2952 break;
2953 }
2954 break;
2955 }
2956 }
2957 return first;
2958}
2959
2960// <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
2961// ::= <closure-type-name>
2962//
2963// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2964//
2965// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
2966
2967template <class C>
2968const char*
2969parse_unnamed_type_name(const char* first, const char* last, C& db)
2970{
2971 if (last - first > 2 && first[0] == 'U')
2972 {
2973 char type = first[1];
2974 switch (type)
2975 {
2976 case 't':
2977 {
2978 db.names.push_back(typename C::String("'unnamed"));
2979 const char* t0 = first+2;
2980 if (t0 == last)
2981 {
2982 db.names.pop_back();
2983 return first;
2984 }
2985 if (std::isdigit(*t0))
2986 {
2987 const char* t1 = t0 + 1;
2988 while (t1 != last && std::isdigit(*t1))
2989 ++t1;
2990 db.names.back().first.append(t0, t1);
2991 t0 = t1;
2992 }
2993 db.names.back().first.push_back('\'');
2994 if (t0 == last || *t0 != '_')
2995 {
2996 db.names.pop_back();
2997 return first;
2998 }
2999 first = t0 + 1;
3000 }
3001 break;
3002 case 'l':
3003 {
3004 db.names.push_back(typename C::String("'lambda'("));
3005 const char* t0 = first+2;
3006 if (first[2] == 'v')
3007 {
3008 db.names.back().first += ')';
3009 ++t0;
3010 }
3011 else
3012 {
3013 const char* t1 = parse_type(t0, last, db);
3014 if (t1 == t0)
3015 {
3016 db.names.pop_back();
3017 return first;
3018 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00003019 if (db.names.size() < 2)
3020 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003021 auto tmp = db.names.back().move_full();
3022 db.names.pop_back();
3023 db.names.back().first.append(tmp);
3024 t0 = t1;
3025 while (true)
3026 {
3027 t1 = parse_type(t0, last, db);
3028 if (t1 == t0)
3029 break;
Howard Hinnant753a30d2013-12-11 19:44:25 +00003030 if (db.names.size() < 2)
3031 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003032 tmp = db.names.back().move_full();
3033 db.names.pop_back();
3034 if (!tmp.empty())
3035 {
3036 db.names.back().first.append(", ");
3037 db.names.back().first.append(tmp);
3038 }
3039 t0 = t1;
3040 }
3041 db.names.back().first.append(")");
3042 }
3043 if (t0 == last || *t0 != 'E')
3044 {
3045 db.names.pop_back();
3046 return first;
3047 }
3048 ++t0;
3049 if (t0 == last)
3050 {
3051 db.names.pop_back();
3052 return first;
3053 }
3054 if (std::isdigit(*t0))
3055 {
3056 const char* t1 = t0 + 1;
3057 while (t1 != last && std::isdigit(*t1))
3058 ++t1;
3059 db.names.back().first.insert(db.names.back().first.begin()+7, t0, t1);
3060 t0 = t1;
3061 }
3062 if (t0 == last || *t0 != '_')
3063 {
3064 db.names.pop_back();
3065 return first;
3066 }
3067 first = t0 + 1;
3068 }
3069 break;
3070 }
3071 }
3072 return first;
3073}
3074
3075// <unqualified-name> ::= <operator-name>
3076// ::= <ctor-dtor-name>
3077// ::= <source-name>
3078// ::= <unnamed-type-name>
3079
3080template <class C>
3081const char*
3082parse_unqualified_name(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003083{
3084 if (first != last)
3085 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00003086 const char* t;
3087 switch (*first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003088 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00003089 case 'C':
3090 case 'D':
3091 t = parse_ctor_dtor_name(first, last, db);
3092 if (t != first)
3093 first = t;
3094 break;
3095 case 'U':
3096 t = parse_unnamed_type_name(first, last, db);
3097 if (t != first)
3098 first = t;
3099 break;
3100 case '1':
3101 case '2':
3102 case '3':
3103 case '4':
3104 case '5':
3105 case '6':
3106 case '7':
3107 case '8':
3108 case '9':
3109 t = parse_source_name(first, last, db);
3110 if (t != first)
3111 first = t;
3112 break;
3113 default:
3114 t = parse_operator_name(first, last, db);
3115 if (t != first)
3116 first = t;
3117 break;
3118 };
3119 }
3120 return first;
3121}
3122
3123// <unscoped-name> ::= <unqualified-name>
3124// ::= St <unqualified-name> # ::std::
3125// extension ::= StL<unqualified-name>
3126
3127template <class C>
3128const char*
3129parse_unscoped_name(const char* first, const char* last, C& db)
3130{
3131 if (last - first >= 2)
3132 {
3133 const char* t0 = first;
3134 bool St = false;
3135 if (first[0] == 'S' && first[1] == 't')
3136 {
3137 t0 += 2;
3138 St = true;
3139 if (t0 != last && *t0 == 'L')
3140 ++t0;
3141 }
3142 const char* t1 = parse_unqualified_name(t0, last, db);
3143 if (t1 != t0)
3144 {
3145 if (St)
Howard Hinnant753a30d2013-12-11 19:44:25 +00003146 {
3147 if (db.names.empty())
3148 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003149 db.names.back().first.insert(0, "std::");
Howard Hinnant753a30d2013-12-11 19:44:25 +00003150 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003151 first = t1;
3152 }
3153 }
3154 return first;
3155}
3156
3157// at <type> # alignof (a type)
3158
3159template <class C>
3160const char*
3161parse_alignof_type(const char* first, const char* last, C& db)
3162{
3163 if (last - first >= 3 && first[0] == 'a' && first[1] == 't')
3164 {
3165 const char* t = parse_type(first+2, last, db);
3166 if (t != first+2)
3167 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003168 if (db.names.empty())
3169 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003170 db.names.back().first = "alignof (" + db.names.back().move_full() + ")";
3171 first = t;
3172 }
3173 }
3174 return first;
3175}
3176
3177// az <expression> # alignof (a expression)
3178
3179template <class C>
3180const char*
3181parse_alignof_expr(const char* first, const char* last, C& db)
3182{
3183 if (last - first >= 3 && first[0] == 'a' && first[1] == 'z')
3184 {
3185 const char* t = parse_expression(first+2, last, db);
3186 if (t != first+2)
3187 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003188 if (db.names.empty())
3189 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003190 db.names.back().first = "alignof (" + db.names.back().move_full() + ")";
3191 first = t;
3192 }
3193 }
3194 return first;
3195}
3196
3197template <class C>
3198const char*
3199parse_noexcept_expression(const char* first, const char* last, C& db)
3200{
3201 const char* t1 = parse_expression(first, last, db);
3202 if (t1 != first)
3203 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003204 if (db.names.empty())
3205 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003206 db.names.back().first = "noexcept (" + db.names.back().move_full() + ")";
3207 first = t1;
3208 }
3209 return first;
3210}
3211
3212template <class C>
3213const char*
3214parse_prefix_expression(const char* first, const char* last, const typename C::String& op, C& db)
3215{
3216 const char* t1 = parse_expression(first, last, db);
3217 if (t1 != first)
3218 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003219 if (db.names.empty())
3220 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003221 db.names.back().first = op + "(" + db.names.back().move_full() + ")";
3222 first = t1;
3223 }
3224 return first;
3225}
3226
3227template <class C>
3228const char*
3229parse_binary_expression(const char* first, const char* last, const typename C::String& op, C& db)
3230{
3231 const char* t1 = parse_expression(first, last, db);
3232 if (t1 != first)
3233 {
3234 const char* t2 = parse_expression(t1, last, db);
3235 if (t2 != t1)
3236 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003237 if (db.names.size() < 2)
3238 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003239 auto op2 = db.names.back().move_full();
3240 db.names.pop_back();
3241 auto op1 = db.names.back().move_full();
3242 auto& nm = db.names.back().first;
3243 nm.clear();
3244 if (op == ">")
3245 nm += '(';
3246 nm += "(" + op1 + ") " + op + " (" + op2 + ")";
3247 if (op == ">")
3248 nm += ')';
3249 first = t2;
3250 }
3251 else
3252 db.names.pop_back();
3253 }
3254 return first;
3255}
3256
3257// <expression> ::= <unary operator-name> <expression>
3258// ::= <binary operator-name> <expression> <expression>
3259// ::= <ternary operator-name> <expression> <expression> <expression>
3260// ::= cl <expression>+ E # call
3261// ::= cv <type> <expression> # conversion with one argument
3262// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
3263// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
3264// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
3265// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
3266// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
3267// ::= [gs] dl <expression> # delete expression
3268// ::= [gs] da <expression> # delete[] expression
3269// ::= pp_ <expression> # prefix ++
3270// ::= mm_ <expression> # prefix --
3271// ::= ti <type> # typeid (type)
3272// ::= te <expression> # typeid (expression)
3273// ::= dc <type> <expression> # dynamic_cast<type> (expression)
3274// ::= sc <type> <expression> # static_cast<type> (expression)
3275// ::= cc <type> <expression> # const_cast<type> (expression)
3276// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
3277// ::= st <type> # sizeof (a type)
3278// ::= sz <expression> # sizeof (an expression)
3279// ::= at <type> # alignof (a type)
3280// ::= az <expression> # alignof (an expression)
3281// ::= nx <expression> # noexcept (expression)
3282// ::= <template-param>
3283// ::= <function-param>
3284// ::= dt <expression> <unresolved-name> # expr.name
3285// ::= pt <expression> <unresolved-name> # expr->name
3286// ::= ds <expression> <expression> # expr.*expr
3287// ::= sZ <template-param> # size of a parameter pack
3288// ::= sZ <function-param> # size of a function parameter pack
3289// ::= sp <expression> # pack expansion
3290// ::= tw <expression> # throw expression
3291// ::= tr # throw with no operand (rethrow)
3292// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
3293// # freestanding dependent name (e.g., T::x),
3294// # objectless nonstatic member reference
3295// ::= <expr-primary>
3296
3297template <class C>
3298const char*
3299parse_expression(const char* first, const char* last, C& db)
3300{
3301 if (last - first >= 2)
3302 {
3303 const char* t = first;
3304 bool parsed_gs = false;
3305 if (last - first >= 4 && t[0] == 'g' && t[1] == 's')
3306 {
3307 t += 2;
3308 parsed_gs = true;
3309 }
3310 switch (*t)
3311 {
3312 case 'L':
3313 first = parse_expr_primary(first, last, db);
3314 break;
3315 case 'T':
3316 first = parse_template_param(first, last, db);
3317 break;
3318 case 'f':
3319 first = parse_function_param(first, last, db);
3320 break;
3321 case 'a':
3322 switch (t[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003323 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00003324 case 'a':
Howard Hinnant93433df2013-06-20 21:49:34 +00003325 t = parse_binary_expression(first+2, last, "&&", db);
3326 if (t != first+2)
3327 first = t;
3328 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003329 case 'd':
Howard Hinnant93433df2013-06-20 21:49:34 +00003330 t = parse_prefix_expression(first+2, last, "&", db);
3331 if (t != first+2)
3332 first = t;
3333 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003334 case 'n':
Howard Hinnant93433df2013-06-20 21:49:34 +00003335 t = parse_binary_expression(first+2, last, "&", db);
3336 if (t != first+2)
3337 first = t;
3338 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003339 case 'N':
Howard Hinnant93433df2013-06-20 21:49:34 +00003340 t = parse_binary_expression(first+2, last, "&=", db);
3341 if (t != first+2)
3342 first = t;
3343 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003344 case 'S':
Howard Hinnant93433df2013-06-20 21:49:34 +00003345 t = parse_binary_expression(first+2, last, "=", db);
3346 if (t != first+2)
3347 first = t;
3348 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003349 case 't':
3350 first = parse_alignof_type(first, last, db);
3351 break;
3352 case 'z':
3353 first = parse_alignof_expr(first, last, db);
3354 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003355 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003356 break;
3357 case 'c':
3358 switch (t[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003359 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00003360 case 'c':
3361 first = parse_const_cast_expr(first, last, db);
3362 break;
3363 case 'l':
3364 first = parse_call_expr(first, last, db);
3365 break;
3366 case 'm':
Howard Hinnant93433df2013-06-20 21:49:34 +00003367 t = parse_binary_expression(first+2, last, ",", db);
3368 if (t != first+2)
3369 first = t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003370 break;
3371 case 'o':
Howard Hinnant93433df2013-06-20 21:49:34 +00003372 t = parse_prefix_expression(first+2, last, "~", db);
3373 if (t != first+2)
3374 first = t;
3375 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003376 case 'v':
3377 first = parse_conversion_expr(first, last, db);
3378 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003379 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003380 break;
3381 case 'd':
3382 switch (t[1])
3383 {
3384 case 'a':
3385 {
3386 const char* t1 = parse_expression(t+2, last, db);
3387 if (t1 != t+2)
3388 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003389 if (db.names.empty())
3390 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003391 db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) +
3392 "delete[] " + db.names.back().move_full();
3393 first = t1;
3394 }
3395 }
3396 break;
3397 case 'c':
3398 first = parse_dynamic_cast_expr(first, last, db);
3399 break;
3400 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00003401 t = parse_prefix_expression(first+2, last, "*", db);
3402 if (t != first+2)
3403 first = t;
3404 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003405 case 'l':
3406 {
3407 const char* t1 = parse_expression(t+2, last, db);
3408 if (t1 != t+2)
3409 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003410 if (db.names.empty())
3411 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003412 db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) +
3413 "delete " + db.names.back().move_full();
3414 first = t1;
3415 }
3416 }
3417 break;
3418 case 'n':
3419 return parse_unresolved_name(first, last, db);
3420 case 's':
3421 first = parse_dot_star_expr(first, last, db);
3422 break;
3423 case 't':
3424 first = parse_dot_expr(first, last, db);
3425 break;
3426 case 'v':
Howard Hinnant93433df2013-06-20 21:49:34 +00003427 t = parse_binary_expression(first+2, last, "/", db);
3428 if (t != first+2)
3429 first = t;
3430 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003431 case 'V':
Howard Hinnant93433df2013-06-20 21:49:34 +00003432 t = parse_binary_expression(first+2, last, "/=", db);
3433 if (t != first+2)
3434 first = t;
3435 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003436 }
3437 break;
3438 case 'e':
3439 switch (t[1])
3440 {
3441 case 'o':
Howard Hinnant93433df2013-06-20 21:49:34 +00003442 t = parse_binary_expression(first+2, last, "^", db);
3443 if (t != first+2)
3444 first = t;
3445 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003446 case 'O':
Howard Hinnant93433df2013-06-20 21:49:34 +00003447 t = parse_binary_expression(first+2, last, "^=", db);
3448 if (t != first+2)
3449 first = t;
3450 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003451 case 'q':
Howard Hinnant93433df2013-06-20 21:49:34 +00003452 t = parse_binary_expression(first+2, last, "==", db);
3453 if (t != first+2)
3454 first = t;
3455 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003456 }
3457 break;
3458 case 'g':
3459 switch (t[1])
3460 {
3461 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00003462 t = parse_binary_expression(first+2, last, ">=", db);
3463 if (t != first+2)
3464 first = t;
3465 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003466 case 't':
Howard Hinnant93433df2013-06-20 21:49:34 +00003467 t = parse_binary_expression(first+2, last, ">", db);
3468 if (t != first+2)
3469 first = t;
3470 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003471 }
3472 break;
3473 case 'i':
3474 if (t[1] == 'x')
3475 {
3476 const char* t1 = parse_expression(first+2, last, db);
3477 if (t1 != first+2)
3478 {
3479 const char* t2 = parse_expression(t1, last, db);
3480 if (t2 != t1)
3481 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003482 if (db.names.size() < 2)
3483 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003484 auto op2 = db.names.back().move_full();
3485 db.names.pop_back();
3486 auto op1 = db.names.back().move_full();
3487 db.names.back() = "(" + op1 + ")[" + op2 + "]";
3488 first = t2;
3489 }
3490 else
3491 db.names.pop_back();
3492 }
3493 }
3494 break;
3495 case 'l':
3496 switch (t[1])
3497 {
3498 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00003499 t = parse_binary_expression(first+2, last, "<=", db);
3500 if (t != first+2)
3501 first = t;
3502 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003503 case 's':
Howard Hinnant93433df2013-06-20 21:49:34 +00003504 t = parse_binary_expression(first+2, last, "<<", db);
3505 if (t != first+2)
3506 first = t;
3507 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003508 case 'S':
Howard Hinnant93433df2013-06-20 21:49:34 +00003509 t = parse_binary_expression(first+2, last, "<<=", db);
3510 if (t != first+2)
3511 first = t;
3512 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003513 case 't':
Howard Hinnant93433df2013-06-20 21:49:34 +00003514 t = parse_binary_expression(first+2, last, "<", db);
3515 if (t != first+2)
3516 first = t;
3517 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003518 }
3519 break;
3520 case 'm':
3521 switch (t[1])
3522 {
3523 case 'i':
Howard Hinnant93433df2013-06-20 21:49:34 +00003524 t = parse_binary_expression(first+2, last, "-", db);
3525 if (t != first+2)
3526 first = t;
3527 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003528 case 'I':
Howard Hinnant93433df2013-06-20 21:49:34 +00003529 t = parse_binary_expression(first+2, last, "-=", db);
3530 if (t != first+2)
3531 first = t;
3532 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003533 case 'l':
Howard Hinnant93433df2013-06-20 21:49:34 +00003534 t = parse_binary_expression(first+2, last, "*", db);
3535 if (t != first+2)
3536 first = t;
3537 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003538 case 'L':
Howard Hinnant93433df2013-06-20 21:49:34 +00003539 t = parse_binary_expression(first+2, last, "*=", db);
3540 if (t != first+2)
3541 first = t;
3542 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003543 case 'm':
3544 if (first+2 != last && first[2] == '_')
Howard Hinnant93433df2013-06-20 21:49:34 +00003545 {
3546 t = parse_prefix_expression(first+3, last, "--", db);
3547 if (t != first+3)
3548 first = t;
3549 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003550 else
3551 {
3552 const char* t1 = parse_expression(first+2, last, db);
3553 if (t1 != first+2)
3554 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003555 if (db.names.empty())
3556 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003557 db.names.back() = "(" + db.names.back().move_full() + ")--";
3558 first = t1;
3559 }
3560 }
3561 break;
3562 }
3563 break;
3564 case 'n':
3565 switch (t[1])
3566 {
3567 case 'a':
3568 case 'w':
3569 first = parse_new_expr(first, last, db);
3570 break;
3571 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00003572 t = parse_binary_expression(first+2, last, "!=", db);
3573 if (t != first+2)
3574 first = t;
3575 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003576 case 'g':
Howard Hinnant93433df2013-06-20 21:49:34 +00003577 t = parse_prefix_expression(first+2, last, "-", db);
3578 if (t != first+2)
3579 first = t;
3580 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003581 case 't':
Howard Hinnant93433df2013-06-20 21:49:34 +00003582 t = parse_prefix_expression(first+2, last, "!", db);
3583 if (t != first+2)
3584 first = t;
3585 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003586 case 'x':
Howard Hinnant93433df2013-06-20 21:49:34 +00003587 t = parse_noexcept_expression(first+2, last, db);
3588 if (t != first+2)
3589 first = t;
3590 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003591 }
3592 break;
3593 case 'o':
3594 switch (t[1])
3595 {
3596 case 'n':
3597 return parse_unresolved_name(first, last, db);
3598 case 'o':
Howard Hinnant93433df2013-06-20 21:49:34 +00003599 t = parse_binary_expression(first+2, last, "||", db);
3600 if (t != first+2)
3601 first = t;
3602 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003603 case 'r':
Howard Hinnant93433df2013-06-20 21:49:34 +00003604 t = parse_binary_expression(first+2, last, "|", db);
3605 if (t != first+2)
3606 first = t;
3607 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003608 case 'R':
Howard Hinnant93433df2013-06-20 21:49:34 +00003609 t = parse_binary_expression(first+2, last, "|=", db);
3610 if (t != first+2)
3611 first = t;
3612 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003613 }
3614 break;
3615 case 'p':
3616 switch (t[1])
3617 {
3618 case 'm':
Howard Hinnant93433df2013-06-20 21:49:34 +00003619 t = parse_binary_expression(first+2, last, "->*", db);
3620 if (t != first+2)
3621 first = t;
3622 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003623 case 'l':
Howard Hinnant93433df2013-06-20 21:49:34 +00003624 t = parse_binary_expression(first+2, last, "+", db);
3625 if (t != first+2)
3626 first = t;
3627 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003628 case 'L':
Howard Hinnant93433df2013-06-20 21:49:34 +00003629 t = parse_binary_expression(first+2, last, "+=", db);
3630 if (t != first+2)
3631 first = t;
3632 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003633 case 'p':
3634 if (first+2 != last && first[2] == '_')
Howard Hinnant93433df2013-06-20 21:49:34 +00003635 {
3636 t = parse_prefix_expression(first+3, last, "++", db);
3637 if (t != first+3)
3638 first = t;
3639 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003640 else
3641 {
3642 const char* t1 = parse_expression(first+2, last, db);
3643 if (t1 != first+2)
3644 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003645 if (db.names.empty())
3646 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003647 db.names.back() = "(" + db.names.back().move_full() + ")++";
3648 first = t1;
3649 }
3650 }
3651 break;
3652 case 's':
Howard Hinnant93433df2013-06-20 21:49:34 +00003653 t = parse_prefix_expression(first+2, last, "+", db);
3654 if (t != first+2)
3655 first = t;
3656 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003657 case 't':
3658 first = parse_arrow_expr(first, last, db);
3659 break;
3660 }
3661 break;
3662 case 'q':
3663 if (t[1] == 'u')
3664 {
3665 const char* t1 = parse_expression(first+2, last, db);
3666 if (t1 != first+2)
3667 {
3668 const char* t2 = parse_expression(t1, last, db);
3669 if (t2 != t1)
3670 {
3671 const char* t3 = parse_expression(t2, last, db);
3672 if (t3 != t2)
3673 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003674 if (db.names.size() < 3)
3675 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003676 auto op3 = db.names.back().move_full();
3677 db.names.pop_back();
3678 auto op2 = db.names.back().move_full();
3679 db.names.pop_back();
3680 auto op1 = db.names.back().move_full();
3681 db.names.back() = "(" + op1 + ") ? (" + op2 + ") : (" + op3 + ")";
3682 first = t3;
3683 }
3684 else
3685 {
3686 db.names.pop_back();
3687 db.names.pop_back();
3688 }
3689 }
3690 else
3691 db.names.pop_back();
3692 }
3693 }
3694 break;
3695 case 'r':
3696 switch (t[1])
3697 {
3698 case 'c':
3699 first = parse_reinterpret_cast_expr(first, last, db);
3700 break;
3701 case 'm':
Howard Hinnant93433df2013-06-20 21:49:34 +00003702 t = parse_binary_expression(first+2, last, "%", db);
3703 if (t != first+2)
3704 first = t;
3705 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003706 case 'M':
Howard Hinnant93433df2013-06-20 21:49:34 +00003707 t = parse_binary_expression(first+2, last, "%=", db);
3708 if (t != first+2)
3709 first = t;
3710 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003711 case 's':
Howard Hinnant93433df2013-06-20 21:49:34 +00003712 t = parse_binary_expression(first+2, last, ">>", db);
3713 if (t != first+2)
3714 first = t;
3715 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003716 case 'S':
Howard Hinnant93433df2013-06-20 21:49:34 +00003717 t = parse_binary_expression(first+2, last, ">>=", db);
3718 if (t != first+2)
3719 first = t;
3720 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003721 }
3722 break;
3723 case 's':
3724 switch (t[1])
3725 {
3726 case 'c':
3727 first = parse_static_cast_expr(first, last, db);
3728 break;
3729 case 'p':
3730 first = parse_pack_expansion(first, last, db);
3731 break;
3732 case 'r':
3733 return parse_unresolved_name(first, last, db);
3734 case 't':
3735 first = parse_sizeof_type_expr(first, last, db);
3736 break;
3737 case 'z':
3738 first = parse_sizeof_expr_expr(first, last, db);
3739 break;
3740 case 'Z':
3741 if (last - t >= 3)
3742 {
3743 switch (t[2])
3744 {
3745 case 'T':
3746 first = parse_sizeof_param_pack_expr(first, last, db);
3747 break;
3748 case 'f':
3749 first = parse_sizeof_function_param_pack_expr(first, last, db);
3750 break;
3751 }
3752 }
3753 break;
3754 }
3755 break;
3756 case 't':
3757 switch (t[1])
3758 {
3759 case 'e':
3760 case 'i':
3761 first = parse_typeid_expr(first, last, db);
3762 break;
3763 case 'r':
3764 db.names.push_back("throw");
3765 first += 2;
3766 break;
3767 case 'w':
3768 first = parse_throw_expr(first, last, db);
3769 break;
3770 }
3771 break;
3772 case '1':
3773 case '2':
3774 case '3':
3775 case '4':
3776 case '5':
3777 case '6':
3778 case '7':
3779 case '8':
3780 case '9':
3781 return parse_unresolved_name(first, last, db);
3782 }
3783 }
3784 return first;
3785}
3786
3787// <template-arg> ::= <type> # type or template
3788// ::= X <expression> E # expression
3789// ::= <expr-primary> # simple expressions
3790// ::= J <template-arg>* E # argument pack
3791// ::= LZ <encoding> E # extension
3792
3793template <class C>
3794const char*
3795parse_template_arg(const char* first, const char* last, C& db)
3796{
3797 if (first != last)
3798 {
3799 const char* t;
3800 switch (*first)
3801 {
3802 case 'X':
3803 t = parse_expression(first+1, last, db);
3804 if (t != first+1)
3805 {
3806 if (t != last && *t == 'E')
3807 first = t+1;
3808 }
3809 break;
3810 case 'J':
3811 t = first+1;
3812 if (t == last)
3813 return first;
3814 while (*t != 'E')
3815 {
3816 const char* t1 = parse_template_arg(t, last, db);
3817 if (t1 == t)
3818 return first;
3819 t = t1;
3820 }
3821 first = t+1;
3822 break;
3823 case 'L':
3824 // <expr-primary> or LZ <encoding> E
3825 if (first+1 != last && first[1] == 'Z')
3826 {
3827 t = parse_encoding(first+2, last, db);
3828 if (t != first+2 && t != last && *t == 'E')
3829 first = t+1;
3830 }
3831 else
3832 first = parse_expr_primary(first, last, db);
3833 break;
3834 default:
3835 // <type>
3836 first = parse_type(first, last, db);
3837 break;
3838 }
3839 }
3840 return first;
3841}
3842
3843// <template-args> ::= I <template-arg>* E
3844// extension, the abi says <template-arg>+
3845
3846template <class C>
3847const char*
3848parse_template_args(const char* first, const char* last, C& db)
3849{
3850 if (last - first >= 2 && *first == 'I')
3851 {
3852 if (db.tag_templates)
3853 db.template_param.back().clear();
3854 const char* t = first+1;
3855 typename C::String args("<");
3856 while (*t != 'E')
3857 {
3858 if (db.tag_templates)
3859 db.template_param.emplace_back(db.names.get_allocator());
3860 size_t k0 = db.names.size();
3861 const char* t1 = parse_template_arg(t, last, db);
3862 size_t k1 = db.names.size();
3863 if (db.tag_templates)
3864 db.template_param.pop_back();
3865 if (t1 == t || t1 == last)
3866 return first;
3867 if (db.tag_templates)
3868 {
3869 db.template_param.back().emplace_back(db.names.get_allocator());
3870 for (size_t k = k0; k < k1; ++k)
3871 db.template_param.back().back().push_back(db.names[k]);
3872 }
3873 for (size_t k = k0; k < k1; ++k)
3874 {
3875 if (args.size() > 1)
3876 args += ", ";
3877 args += db.names[k].move_full();
3878 }
3879 for (; k1 != k0; --k1)
3880 db.names.pop_back();
3881 t = t1;
3882 }
3883 first = t + 1;
3884 if (args.back() != '>')
3885 args += ">";
3886 else
3887 args += " >";
3888 db.names.push_back(std::move(args));
3889
3890 }
3891 return first;
3892}
3893
3894// <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
3895// ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
3896//
3897// <prefix> ::= <prefix> <unqualified-name>
3898// ::= <template-prefix> <template-args>
3899// ::= <template-param>
3900// ::= <decltype>
3901// ::= # empty
3902// ::= <substitution>
3903// ::= <prefix> <data-member-prefix>
3904// extension ::= L
3905//
3906// <template-prefix> ::= <prefix> <template unqualified-name>
3907// ::= <template-param>
3908// ::= <substitution>
3909
3910template <class C>
3911const char*
Richard Smith24ecd092014-05-12 18:44:13 +00003912parse_nested_name(const char* first, const char* last, C& db,
3913 bool* ends_with_template_args)
Howard Hinnant6c33e762013-06-17 18:10:34 +00003914{
3915 if (first != last && *first == 'N')
3916 {
3917 unsigned cv;
3918 const char* t0 = parse_cv_qualifiers(first+1, last, cv);
3919 if (t0 == last)
3920 return first;
3921 db.ref = 0;
3922 if (*t0 == 'R')
3923 {
3924 db.ref = 1;
3925 ++t0;
3926 }
3927 else if (*t0 == 'O')
3928 {
3929 db.ref = 2;
3930 ++t0;
3931 }
3932 db.names.emplace_back();
3933 if (last - t0 >= 2 && t0[0] == 'S' && t0[1] == 't')
3934 {
3935 t0 += 2;
3936 db.names.back().first = "std";
3937 }
3938 if (t0 == last)
3939 {
3940 db.names.pop_back();
3941 return first;
3942 }
3943 bool pop_subs = false;
Richard Smith24ecd092014-05-12 18:44:13 +00003944 bool component_ends_with_template_args = false;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003945 while (*t0 != 'E')
3946 {
Richard Smith24ecd092014-05-12 18:44:13 +00003947 component_ends_with_template_args = false;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003948 const char* t1;
3949 switch (*t0)
3950 {
3951 case 'S':
3952 if (t0 + 1 != last && t0[1] == 't')
3953 goto do_parse_unqualified_name;
3954 t1 = parse_substitution(t0, last, db);
3955 if (t1 != t0 && t1 != last)
3956 {
3957 auto name = db.names.back().move_full();
3958 db.names.pop_back();
3959 if (!db.names.back().first.empty())
3960 {
3961 db.names.back().first += "::" + name;
3962 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
3963 }
3964 else
3965 db.names.back().first = name;
3966 pop_subs = true;
3967 t0 = t1;
3968 }
3969 else
3970 return first;
3971 break;
3972 case 'T':
3973 t1 = parse_template_param(t0, last, db);
3974 if (t1 != t0 && t1 != last)
3975 {
3976 auto name = db.names.back().move_full();
3977 db.names.pop_back();
3978 if (!db.names.back().first.empty())
3979 db.names.back().first += "::" + name;
3980 else
3981 db.names.back().first = name;
3982 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
3983 pop_subs = true;
3984 t0 = t1;
3985 }
3986 else
3987 return first;
3988 break;
3989 case 'D':
3990 if (t0 + 1 != last && t0[1] != 't' && t0[1] != 'T')
3991 goto do_parse_unqualified_name;
3992 t1 = parse_decltype(t0, last, db);
3993 if (t1 != t0 && t1 != last)
3994 {
3995 auto name = db.names.back().move_full();
3996 db.names.pop_back();
3997 if (!db.names.back().first.empty())
3998 db.names.back().first += "::" + name;
3999 else
4000 db.names.back().first = name;
4001 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
4002 pop_subs = true;
4003 t0 = t1;
4004 }
4005 else
4006 return first;
4007 break;
4008 case 'I':
4009 t1 = parse_template_args(t0, last, db);
4010 if (t1 != t0 && t1 != last)
4011 {
4012 auto name = db.names.back().move_full();
4013 db.names.pop_back();
4014 db.names.back().first += name;
4015 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
4016 t0 = t1;
Richard Smith24ecd092014-05-12 18:44:13 +00004017 component_ends_with_template_args = true;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004018 }
4019 else
4020 return first;
4021 break;
4022 case 'L':
4023 if (++t0 == last)
4024 return first;
4025 break;
4026 default:
4027 do_parse_unqualified_name:
4028 t1 = parse_unqualified_name(t0, last, db);
4029 if (t1 != t0 && t1 != last)
4030 {
4031 auto name = db.names.back().move_full();
4032 db.names.pop_back();
4033 if (!db.names.back().first.empty())
4034 db.names.back().first += "::" + name;
4035 else
4036 db.names.back().first = name;
4037 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
4038 pop_subs = true;
4039 t0 = t1;
4040 }
4041 else
4042 return first;
4043 }
4044 }
4045 first = t0 + 1;
4046 db.cv = cv;
Howard Hinnantf6725172013-06-21 17:04:24 +00004047 if (pop_subs && !db.subs.empty())
Howard Hinnant6c33e762013-06-17 18:10:34 +00004048 db.subs.pop_back();
Richard Smith24ecd092014-05-12 18:44:13 +00004049 if (ends_with_template_args)
4050 *ends_with_template_args = component_ends_with_template_args;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004051 }
4052 return first;
4053}
4054
4055// <discriminator> := _ <non-negative number> # when number < 10
4056// := __ <non-negative number> _ # when number >= 10
Marshall Clow6c6d9cb2015-10-08 03:02:09 +00004057// extension := decimal-digit+ # at the end of string
Howard Hinnant6c33e762013-06-17 18:10:34 +00004058
4059const char*
4060parse_discriminator(const char* first, const char* last)
4061{
4062 // parse but ignore discriminator
4063 if (first != last)
4064 {
4065 if (*first == '_')
4066 {
4067 const char* t1 = first+1;
4068 if (t1 != last)
4069 {
4070 if (std::isdigit(*t1))
4071 first = t1+1;
4072 else if (*t1 == '_')
4073 {
4074 for (++t1; t1 != last && std::isdigit(*t1); ++t1)
4075 ;
4076 if (t1 != last && *t1 == '_')
4077 first = t1 + 1;
4078 }
4079 }
4080 }
4081 else if (std::isdigit(*first))
4082 {
4083 const char* t1 = first+1;
4084 for (; t1 != last && std::isdigit(*t1); ++t1)
4085 ;
Marshall Clow6c6d9cb2015-10-08 03:02:09 +00004086 if (t1 == last)
4087 first = last;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004088 }
4089 }
4090 return first;
4091}
4092
4093// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
4094// := Z <function encoding> E s [<discriminator>]
4095// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
4096
4097template <class C>
4098const char*
Richard Smith24ecd092014-05-12 18:44:13 +00004099parse_local_name(const char* first, const char* last, C& db,
4100 bool* ends_with_template_args)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004101{
4102 if (first != last && *first == 'Z')
4103 {
4104 const char* t = parse_encoding(first+1, last, db);
4105 if (t != first+1 && t != last && *t == 'E' && ++t != last)
4106 {
4107 switch (*t)
4108 {
4109 case 's':
4110 first = parse_discriminator(t+1, last);
Howard Hinnant753a30d2013-12-11 19:44:25 +00004111 if (db.names.empty())
4112 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004113 db.names.back().first.append("::string literal");
4114 break;
4115 case 'd':
4116 if (++t != last)
4117 {
4118 const char* t1 = parse_number(t, last);
4119 if (t1 != last && *t1 == '_')
4120 {
4121 t = t1 + 1;
Richard Smith24ecd092014-05-12 18:44:13 +00004122 t1 = parse_name(t, last, db,
4123 ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004124 if (t1 != t)
4125 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004126 if (db.names.size() < 2)
4127 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004128 auto name = db.names.back().move_full();
4129 db.names.pop_back();
4130 db.names.back().first.append("::");
4131 db.names.back().first.append(name);
4132 first = t1;
4133 }
4134 else
4135 db.names.pop_back();
4136 }
4137 }
4138 break;
4139 default:
4140 {
Richard Smith24ecd092014-05-12 18:44:13 +00004141 const char* t1 = parse_name(t, last, db,
4142 ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004143 if (t1 != t)
4144 {
4145 // parse but ignore discriminator
4146 first = parse_discriminator(t1, last);
Howard Hinnant753a30d2013-12-11 19:44:25 +00004147 if (db.names.size() < 2)
4148 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004149 auto name = db.names.back().move_full();
4150 db.names.pop_back();
4151 db.names.back().first.append("::");
4152 db.names.back().first.append(name);
4153 }
4154 else
4155 db.names.pop_back();
4156 }
4157 break;
4158 }
4159 }
4160 }
4161 return first;
4162}
4163
4164// <name> ::= <nested-name> // N
4165// ::= <local-name> # See Scope Encoding below // Z
4166// ::= <unscoped-template-name> <template-args>
4167// ::= <unscoped-name>
4168
4169// <unscoped-template-name> ::= <unscoped-name>
4170// ::= <substitution>
4171
4172template <class C>
4173const char*
Richard Smith24ecd092014-05-12 18:44:13 +00004174parse_name(const char* first, const char* last, C& db,
4175 bool* ends_with_template_args)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004176{
4177 if (last - first >= 2)
4178 {
4179 const char* t0 = first;
4180 // extension: ignore L here
4181 if (*t0 == 'L')
4182 ++t0;
4183 switch (*t0)
4184 {
4185 case 'N':
4186 {
Richard Smith24ecd092014-05-12 18:44:13 +00004187 const char* t1 = parse_nested_name(t0, last, db,
4188 ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004189 if (t1 != t0)
4190 first = t1;
4191 break;
4192 }
4193 case 'Z':
4194 {
Richard Smith24ecd092014-05-12 18:44:13 +00004195 const char* t1 = parse_local_name(t0, last, db,
4196 ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004197 if (t1 != t0)
4198 first = t1;
4199 break;
4200 }
4201 default:
4202 {
4203 const char* t1 = parse_unscoped_name(t0, last, db);
4204 if (t1 != t0)
4205 {
4206 if (t1 != last && *t1 == 'I') // <unscoped-template-name> <template-args>
4207 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004208 if (db.names.empty())
4209 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004210 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
4211 t0 = t1;
4212 t1 = parse_template_args(t0, last, db);
4213 if (t1 != t0)
4214 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004215 if (db.names.size() < 2)
4216 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004217 auto tmp = db.names.back().move_full();
4218 db.names.pop_back();
4219 db.names.back().first += tmp;
4220 first = t1;
Richard Smith24ecd092014-05-12 18:44:13 +00004221 if (ends_with_template_args)
4222 *ends_with_template_args = true;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004223 }
4224 }
4225 else // <unscoped-name>
4226 first = t1;
4227 }
4228 else
4229 { // try <substitution> <template-args>
4230 t1 = parse_substitution(t0, last, db);
Howard Hinnantb4033ff2013-06-20 01:55:07 +00004231 if (t1 != t0 && t1 != last && *t1 == 'I')
Howard Hinnant6c33e762013-06-17 18:10:34 +00004232 {
4233 t0 = t1;
4234 t1 = parse_template_args(t0, last, db);
4235 if (t1 != t0)
4236 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004237 if (db.names.size() < 2)
4238 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004239 auto tmp = db.names.back().move_full();
4240 db.names.pop_back();
4241 db.names.back().first += tmp;
4242 first = t1;
Richard Smith24ecd092014-05-12 18:44:13 +00004243 if (ends_with_template_args)
4244 *ends_with_template_args = true;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004245 }
4246 }
4247 }
4248 break;
4249 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004250 }
4251 }
4252 return first;
4253}
4254
4255// <call-offset> ::= h <nv-offset> _
4256// ::= v <v-offset> _
4257//
4258// <nv-offset> ::= <offset number>
4259// # non-virtual base override
4260//
4261// <v-offset> ::= <offset number> _ <virtual offset number>
4262// # virtual base override, with vcall offset
4263
4264const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004265parse_call_offset(const char* first, const char* last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004266{
4267 if (first != last)
4268 {
4269 switch (*first)
4270 {
4271 case 'h':
4272 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004273 const char* t = parse_number(first + 1, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004274 if (t != first + 1 && t != last && *t == '_')
4275 first = t + 1;
4276 }
4277 break;
4278 case 'v':
4279 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004280 const char* t = parse_number(first + 1, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004281 if (t != first + 1 && t != last && *t == '_')
4282 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004283 const char* t2 = parse_number(++t, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004284 if (t2 != t && t2 != last && *t2 == '_')
4285 first = t2 + 1;
4286 }
4287 }
4288 break;
4289 }
4290 }
4291 return first;
4292}
4293
4294// <special-name> ::= TV <type> # virtual table
4295// ::= TT <type> # VTT structure (construction vtable index)
4296// ::= TI <type> # typeinfo structure
4297// ::= TS <type> # typeinfo name (null-terminated byte string)
4298// ::= Tc <call-offset> <call-offset> <base encoding>
4299// # base is the nominal target function of thunk
4300// # first call-offset is 'this' adjustment
4301// # second call-offset is result adjustment
4302// ::= T <call-offset> <base encoding>
4303// # base is the nominal target function of thunk
4304// ::= GV <object name> # Guard variable for one-time initialization
4305// # No <type>
Howard Hinnantf2700352011-12-09 20:07:56 +00004306// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
4307// extension ::= GR <object name> # reference temporary for object
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004308
Howard Hinnant6c33e762013-06-17 18:10:34 +00004309template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004310const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004311parse_special_name(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004312{
4313 if (last - first > 2)
4314 {
4315 const char* t;
4316 switch (*first)
4317 {
4318 case 'T':
4319 switch (first[1])
4320 {
4321 case 'V':
4322 // TV <type> # virtual table
Howard Hinnant6c33e762013-06-17 18:10:34 +00004323 t = parse_type(first+2, last, db);
4324 if (t != first+2)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004325 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004326 if (db.names.empty())
4327 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004328 db.names.back().first.insert(0, "vtable for ");
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004329 first = t;
4330 }
4331 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004332 case 'T':
4333 // TT <type> # VTT structure (construction vtable index)
4334 t = parse_type(first+2, last, db);
Howard Hinnantf2700352011-12-09 20:07:56 +00004335 if (t != first+2)
4336 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004337 if (db.names.empty())
4338 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004339 db.names.back().first.insert(0, "VTT for ");
4340 first = t;
4341 }
4342 break;
4343 case 'I':
4344 // TI <type> # typeinfo structure
4345 t = parse_type(first+2, last, db);
4346 if (t != first+2)
4347 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004348 if (db.names.empty())
4349 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004350 db.names.back().first.insert(0, "typeinfo for ");
4351 first = t;
4352 }
4353 break;
4354 case 'S':
4355 // TS <type> # typeinfo name (null-terminated byte string)
4356 t = parse_type(first+2, last, db);
4357 if (t != first+2)
4358 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004359 if (db.names.empty())
4360 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004361 db.names.back().first.insert(0, "typeinfo name for ");
4362 first = t;
4363 }
4364 break;
4365 case 'c':
4366 // Tc <call-offset> <call-offset> <base encoding>
4367 {
4368 const char* t0 = parse_call_offset(first+2, last);
4369 if (t0 == first+2)
4370 break;
4371 const char* t1 = parse_call_offset(t0, last);
4372 if (t1 == t0)
4373 break;
4374 t = parse_encoding(t1, last, db);
4375 if (t != t1)
4376 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004377 if (db.names.empty())
4378 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004379 db.names.back().first.insert(0, "covariant return thunk to ");
4380 first = t;
4381 }
4382 }
4383 break;
4384 case 'C':
4385 // extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
4386 t = parse_type(first+2, last, db);
4387 if (t != first+2)
4388 {
4389 const char* t0 = parse_number(t, last);
Howard Hinnantf2700352011-12-09 20:07:56 +00004390 if (t0 != t && t0 != last && *t0 == '_')
4391 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004392 const char* t1 = parse_type(++t0, last, db);
Howard Hinnantf2700352011-12-09 20:07:56 +00004393 if (t1 != t0)
4394 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004395 if (db.names.size() < 2)
4396 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004397 auto left = db.names.back().move_full();
4398 db.names.pop_back();
4399 db.names.back().first = "construction vtable for " +
4400 std::move(left) + "-in-" +
4401 db.names.back().move_full();
4402 first = t1;
Howard Hinnantf2700352011-12-09 20:07:56 +00004403 }
4404 }
4405 }
4406 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004407 default:
4408 // T <call-offset> <base encoding>
4409 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004410 const char* t0 = parse_call_offset(first+1, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004411 if (t0 == first+1)
4412 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004413 t = parse_encoding(t0, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004414 if (t != t0)
4415 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004416 if (db.names.empty())
4417 return first;
Marshall Clowfdccce62015-10-12 20:45:05 +00004418 if (first[1] == 'v')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004419 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004420 db.names.back().first.insert(0, "virtual thunk to ");
4421 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004422 }
4423 else
4424 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004425 db.names.back().first.insert(0, "non-virtual thunk to ");
4426 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004427 }
4428 }
4429 }
4430 break;
4431 }
4432 break;
4433 case 'G':
Howard Hinnantf2700352011-12-09 20:07:56 +00004434 switch (first[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004435 {
Howard Hinnantf2700352011-12-09 20:07:56 +00004436 case 'V':
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004437 // GV <object name> # Guard variable for one-time initialization
Howard Hinnant6c33e762013-06-17 18:10:34 +00004438 t = parse_name(first+2, last, db);
4439 if (t != first+2)
4440 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004441 if (db.names.empty())
4442 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004443 db.names.back().first.insert(0, "guard variable for ");
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004444 first = t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004445 }
Howard Hinnantf2700352011-12-09 20:07:56 +00004446 break;
4447 case 'R':
4448 // extension ::= GR <object name> # reference temporary for object
Howard Hinnant6c33e762013-06-17 18:10:34 +00004449 t = parse_name(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004450 if (t != first+2)
4451 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004452 if (db.names.empty())
4453 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004454 db.names.back().first.insert(0, "reference temporary for ");
4455 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004456 }
4457 break;
4458 }
4459 break;
4460 }
4461 }
4462 return first;
4463}
4464
Howard Hinnant753a30d2013-12-11 19:44:25 +00004465template <class T>
4466class save_value
4467{
4468 T& restore_;
4469 T original_value_;
4470public:
4471 save_value(T& restore)
4472 : restore_(restore),
4473 original_value_(restore)
4474 {}
4475
4476 ~save_value()
4477 {
4478 restore_ = std::move(original_value_);
4479 }
4480
4481 save_value(const save_value&) = delete;
4482 save_value& operator=(const save_value&) = delete;
4483};
4484
Howard Hinnant6c33e762013-06-17 18:10:34 +00004485// <encoding> ::= <function name> <bare-function-type>
4486// ::= <data name>
4487// ::= <special-name>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004488
Howard Hinnant6c33e762013-06-17 18:10:34 +00004489template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004490const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004491parse_encoding(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004492{
4493 if (first != last)
4494 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004495 save_value<decltype(db.encoding_depth)> su(db.encoding_depth);
4496 ++db.encoding_depth;
4497 save_value<decltype(db.tag_templates)> sb(db.tag_templates);
4498 if (db.encoding_depth > 1)
4499 db.tag_templates = true;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004500 switch (*first)
4501 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004502 case 'G':
4503 case 'T':
4504 first = parse_special_name(first, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004505 break;
4506 default:
Howard Hinnant6c33e762013-06-17 18:10:34 +00004507 {
Richard Smith24ecd092014-05-12 18:44:13 +00004508 bool ends_with_template_args = false;
4509 const char* t = parse_name(first, last, db,
4510 &ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004511 unsigned cv = db.cv;
4512 unsigned ref = db.ref;
4513 if (t != first)
Howard Hinnantab87dcf2011-12-15 20:02:15 +00004514 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004515 if (t != last && *t != 'E' && *t != '.')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004516 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004517 save_value<bool> sb2(db.tag_templates);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004518 db.tag_templates = false;
4519 const char* t2;
4520 typename C::String ret2;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004521 if (db.names.empty())
4522 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004523 const typename C::String& nm = db.names.back().first;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004524 if (nm.empty())
4525 return first;
Richard Smith24ecd092014-05-12 18:44:13 +00004526 if (!db.parsed_ctor_dtor_cv && ends_with_template_args)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004527 {
4528 t2 = parse_type(t, last, db);
4529 if (t2 == t)
4530 return first;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004531 if (db.names.size() < 2)
4532 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004533 auto ret1 = std::move(db.names.back().first);
4534 ret2 = std::move(db.names.back().second);
4535 if (ret2.empty())
4536 ret1 += ' ';
4537 db.names.pop_back();
4538 db.names.back().first.insert(0, ret1);
4539 t = t2;
4540 }
4541 db.names.back().first += '(';
4542 if (t != last && *t == 'v')
4543 {
4544 ++t;
4545 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004546 else
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004547 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004548 bool first_arg = true;
4549 while (true)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004550 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004551 size_t k0 = db.names.size();
4552 t2 = parse_type(t, last, db);
4553 size_t k1 = db.names.size();
4554 if (t2 == t)
4555 break;
4556 if (k1 > k0)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004557 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004558 typename C::String tmp;
4559 for (size_t k = k0; k < k1; ++k)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004560 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004561 if (!tmp.empty())
4562 tmp += ", ";
4563 tmp += db.names[k].move_full();
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004564 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004565 for (size_t k = k0; k < k1; ++k)
4566 db.names.pop_back();
4567 if (!tmp.empty())
4568 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004569 if (db.names.empty())
4570 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004571 if (!first_arg)
4572 db.names.back().first += ", ";
4573 else
4574 first_arg = false;
4575 db.names.back().first += tmp;
4576 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004577 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004578 t = t2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004579 }
4580 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00004581 if (db.names.empty())
4582 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004583 db.names.back().first += ')';
4584 if (cv & 1)
4585 db.names.back().first.append(" const");
4586 if (cv & 2)
4587 db.names.back().first.append(" volatile");
4588 if (cv & 4)
4589 db.names.back().first.append(" restrict");
4590 if (ref == 1)
4591 db.names.back().first.append(" &");
4592 else if (ref == 2)
4593 db.names.back().first.append(" &&");
4594 db.names.back().first += ret2;
4595 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004596 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004597 else
4598 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004599 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004600 break;
4601 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004602 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004603 }
4604 return first;
4605}
4606
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004607// _block_invoke
4608// _block_invoke<decimal-digit>+
4609// _block_invoke_<decimal-digit>+
4610
Howard Hinnant6c33e762013-06-17 18:10:34 +00004611template <class C>
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004612const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004613parse_block_invoke(const char* first, const char* last, C& db)
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004614{
4615 if (last - first >= 13)
4616 {
4617 const char test[] = "_block_invoke";
4618 const char* t = first;
4619 for (int i = 0; i < 13; ++i, ++t)
4620 {
4621 if (*t != test[i])
4622 return first;
4623 }
4624 if (t != last)
4625 {
4626 if (*t == '_')
4627 {
4628 // must have at least 1 decimal digit
Howard Hinnant6c33e762013-06-17 18:10:34 +00004629 if (++t == last || !std::isdigit(*t))
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004630 return first;
4631 ++t;
4632 }
4633 // parse zero or more digits
4634 while (t != last && isdigit(*t))
4635 ++t;
4636 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00004637 if (db.names.empty())
4638 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004639 db.names.back().first.insert(0, "invocation function for block in ");
4640 first = t;
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004641 }
4642 return first;
4643}
4644
Howard Hinnant6c33e762013-06-17 18:10:34 +00004645// extension
4646// <dot-suffix> := .<anything and everything>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004647
Howard Hinnant6c33e762013-06-17 18:10:34 +00004648template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004649const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004650parse_dot_suffix(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004651{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004652 if (first != last && *first == '.')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004653 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004654 if (db.names.empty())
4655 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004656 db.names.back().first += " (" + typename C::String(first, last) + ")";
4657 first = last;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004658 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004659 return first;
4660}
4661
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004662// <block-involcaton-function> ___Z<encoding>_block_invoke
4663// <block-involcaton-function> ___Z<encoding>_block_invoke<decimal-digit>+
4664// <block-involcaton-function> ___Z<encoding>_block_invoke_<decimal-digit>+
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004665// <mangled-name> ::= _Z<encoding>
4666// ::= <type>
4667
Howard Hinnant6c33e762013-06-17 18:10:34 +00004668template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004669void
Howard Hinnant6c33e762013-06-17 18:10:34 +00004670demangle(const char* first, const char* last, C& db, int& status)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004671{
Howard Hinnanteb8d46c2013-06-23 17:14:35 +00004672 if (first >= last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004673 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004674 status = invalid_mangled_name;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004675 return;
4676 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004677 if (*first == '_')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004678 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004679 if (last - first >= 4)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004680 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004681 if (first[1] == 'Z')
4682 {
4683 const char* t = parse_encoding(first+2, last, db);
4684 if (t != first+2 && t != last && *t == '.')
4685 t = parse_dot_suffix(t, last, db);
4686 if (t != last)
4687 status = invalid_mangled_name;
4688 }
4689 else if (first[1] == '_' && first[2] == '_' && first[3] == 'Z')
4690 {
4691 const char* t = parse_encoding(first+4, last, db);
4692 if (t != first+4 && t != last)
4693 {
4694 const char* t1 = parse_block_invoke(t, last, db);
4695 if (t1 != last)
4696 status = invalid_mangled_name;
4697 }
4698 else
4699 status = invalid_mangled_name;
4700 }
4701 else
4702 status = invalid_mangled_name;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004703 }
4704 else
Howard Hinnant6c33e762013-06-17 18:10:34 +00004705 status = invalid_mangled_name;
4706 }
4707 else
4708 {
4709 const char* t = parse_type(first, last, db);
4710 if (t != last)
4711 status = invalid_mangled_name;
4712 }
Howard Hinnanteb8d46c2013-06-23 17:14:35 +00004713 if (status == success && db.names.empty())
4714 status = invalid_mangled_name;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004715}
4716
Howard Hinnant6c33e762013-06-17 18:10:34 +00004717template <std::size_t N>
4718class arena
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004719{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004720 static const std::size_t alignment = 16;
4721 alignas(alignment) char buf_[N];
4722 char* ptr_;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004723
Howard Hinnant6c33e762013-06-17 18:10:34 +00004724 std::size_t
4725 align_up(std::size_t n) noexcept
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +00004726 {return (n + (alignment-1)) & ~(alignment-1);}
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004727
Howard Hinnant6c33e762013-06-17 18:10:34 +00004728 bool
4729 pointer_in_buffer(char* p) noexcept
4730 {return buf_ <= p && p <= buf_ + N;}
4731
4732public:
4733 arena() noexcept : ptr_(buf_) {}
4734 ~arena() {ptr_ = nullptr;}
4735 arena(const arena&) = delete;
4736 arena& operator=(const arena&) = delete;
4737
4738 char* allocate(std::size_t n);
4739 void deallocate(char* p, std::size_t n) noexcept;
4740
4741 static constexpr std::size_t size() {return N;}
4742 std::size_t used() const {return static_cast<std::size_t>(ptr_ - buf_);}
4743 void reset() {ptr_ = buf_;}
4744};
4745
4746template <std::size_t N>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004747char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004748arena<N>::allocate(std::size_t n)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004749{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004750 n = align_up(n);
4751 if (static_cast<std::size_t>(buf_ + N - ptr_) >= n)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004752 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004753 char* r = ptr_;
4754 ptr_ += n;
4755 return r;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004756 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004757 return static_cast<char*>(std::malloc(n));
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004758}
4759
Howard Hinnant6c33e762013-06-17 18:10:34 +00004760template <std::size_t N>
4761void
4762arena<N>::deallocate(char* p, std::size_t n) noexcept
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004763{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004764 if (pointer_in_buffer(p))
4765 {
4766 n = align_up(n);
4767 if (p + n == ptr_)
4768 ptr_ = p;
4769 }
4770 else
4771 std::free(p);
4772}
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004773
Howard Hinnant6c33e762013-06-17 18:10:34 +00004774template <class T, std::size_t N>
4775class short_alloc
4776{
4777 arena<N>& a_;
4778public:
4779 typedef T value_type;
4780
4781public:
4782 template <class _Up> struct rebind {typedef short_alloc<_Up, N> other;};
4783
4784 short_alloc(arena<N>& a) noexcept : a_(a) {}
4785 template <class U>
4786 short_alloc(const short_alloc<U, N>& a) noexcept
4787 : a_(a.a_) {}
4788 short_alloc(const short_alloc&) = default;
4789 short_alloc& operator=(const short_alloc&) = delete;
4790
4791 T* allocate(std::size_t n)
4792 {
4793 return reinterpret_cast<T*>(a_.allocate(n*sizeof(T)));
4794 }
4795 void deallocate(T* p, std::size_t n) noexcept
4796 {
4797 a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
4798 }
4799
4800 template <class T1, std::size_t N1, class U, std::size_t M>
4801 friend
4802 bool
4803 operator==(const short_alloc<T1, N1>& x, const short_alloc<U, M>& y) noexcept;
4804
4805 template <class U, std::size_t M> friend class short_alloc;
4806};
4807
4808template <class T, std::size_t N, class U, std::size_t M>
4809inline
4810bool
4811operator==(const short_alloc<T, N>& x, const short_alloc<U, M>& y) noexcept
4812{
4813 return N == M && &x.a_ == &y.a_;
4814}
4815
4816template <class T, std::size_t N, class U, std::size_t M>
4817inline
4818bool
4819operator!=(const short_alloc<T, N>& x, const short_alloc<U, M>& y) noexcept
4820{
4821 return !(x == y);
4822}
4823
4824template <class T>
4825class malloc_alloc
4826{
4827public:
4828 typedef T value_type;
Nico Weberb4c998b2015-09-20 18:10:46 +00004829 typedef T& reference;
4830 typedef const T& const_reference;
4831 typedef T* pointer;
4832 typedef const T* const_pointer;
4833 typedef std::size_t size_type;
4834 typedef std::ptrdiff_t difference_type;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004835
4836 malloc_alloc() = default;
4837 template <class U> malloc_alloc(const malloc_alloc<U>&) noexcept {}
4838
4839 T* allocate(std::size_t n)
4840 {
4841 return static_cast<T*>(std::malloc(n*sizeof(T)));
4842 }
4843 void deallocate(T* p, std::size_t) noexcept
4844 {
4845 std::free(p);
4846 }
Nico Weberb4c998b2015-09-20 18:10:46 +00004847
4848 template <class U> struct rebind { using other = malloc_alloc<U>; };
4849 template <class U, class... Args>
4850 void construct(U* p, Args&&... args)
4851 {
4852 ::new ((void*)p) U(std::forward<Args>(args)...);
4853 }
4854 void destroy(T* p)
4855 {
4856 p->~T();
4857 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004858};
4859
4860template <class T, class U>
4861inline
4862bool
4863operator==(const malloc_alloc<T>&, const malloc_alloc<U>&) noexcept
4864{
4865 return true;
4866}
4867
4868template <class T, class U>
4869inline
4870bool
4871operator!=(const malloc_alloc<T>& x, const malloc_alloc<U>& y) noexcept
4872{
4873 return !(x == y);
4874}
4875
4876const size_t bs = 4 * 1024;
4877template <class T> using Alloc = short_alloc<T, bs>;
4878template <class T> using Vector = std::vector<T, Alloc<T>>;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004879
Nico Weber2b683fb2014-05-30 17:27:21 +00004880template <class StrT>
Howard Hinnant6c33e762013-06-17 18:10:34 +00004881struct string_pair
4882{
Nico Weber2b683fb2014-05-30 17:27:21 +00004883 StrT first;
4884 StrT second;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004885
4886 string_pair() = default;
Nico Weber2b683fb2014-05-30 17:27:21 +00004887 string_pair(StrT f) : first(std::move(f)) {}
4888 string_pair(StrT f, StrT s)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004889 : first(std::move(f)), second(std::move(s)) {}
4890 template <size_t N>
4891 string_pair(const char (&s)[N]) : first(s, N-1) {}
4892
4893 size_t size() const {return first.size() + second.size();}
Nico Weber2b683fb2014-05-30 17:27:21 +00004894 StrT full() const {return first + second;}
4895 StrT move_full() {return std::move(first) + std::move(second);}
Howard Hinnant6c33e762013-06-17 18:10:34 +00004896};
4897
Howard Hinnant061240c2013-10-22 16:45:48 +00004898struct Db
4899{
Nico Weber2b683fb2014-05-30 17:27:21 +00004900 typedef std::basic_string<char, std::char_traits<char>,
4901 malloc_alloc<char>> String;
4902 typedef Vector<string_pair<String>> sub_type;
Howard Hinnant061240c2013-10-22 16:45:48 +00004903 typedef Vector<sub_type> template_param_type;
Nico Weber2b683fb2014-05-30 17:27:21 +00004904 sub_type names;
4905 template_param_type subs;
Howard Hinnant061240c2013-10-22 16:45:48 +00004906 Vector<template_param_type> template_param;
4907 unsigned cv;
4908 unsigned ref;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004909 unsigned encoding_depth;
Howard Hinnant061240c2013-10-22 16:45:48 +00004910 bool parsed_ctor_dtor_cv;
4911 bool tag_templates;
4912 bool fix_forward_references;
4913 bool try_to_parse_template_args;
4914
4915 template <size_t N>
4916 Db(arena<N>& ar) :
4917 names(ar),
4918 subs(0, names, ar),
4919 template_param(0, subs, ar)
4920 {}
4921};
4922
Howard Hinnant6c33e762013-06-17 18:10:34 +00004923} // unnamed namespace
4924
Howard Hinnant6c33e762013-06-17 18:10:34 +00004925extern "C"
Nico Weber298baa32014-06-25 23:55:37 +00004926__attribute__ ((__visibility__("default")))
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004927char*
4928__cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status)
4929{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004930 if (mangled_name == nullptr || (buf != nullptr && n == nullptr))
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004931 {
4932 if (status)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004933 *status = invalid_args;
4934 return nullptr;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004935 }
Howard Hinnant8ad6a222013-07-26 22:14:53 +00004936 size_t internal_size = buf != nullptr ? *n : 0;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004937 arena<bs> a;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004938 Db db(a);
4939 db.cv = 0;
Howard Hinnant19e36dd2013-06-19 13:43:18 +00004940 db.ref = 0;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004941 db.encoding_depth = 0;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004942 db.parsed_ctor_dtor_cv = false;
4943 db.tag_templates = true;
4944 db.template_param.emplace_back(a);
4945 db.fix_forward_references = false;
4946 db.try_to_parse_template_args = true;
4947 int internal_status = success;
Howard Hinnantb2d1f942013-06-23 19:52:45 +00004948 size_t len = std::strlen(mangled_name);
4949 demangle(mangled_name, mangled_name + len, db,
Howard Hinnant6c33e762013-06-17 18:10:34 +00004950 internal_status);
Howard Hinnantb2d1f942013-06-23 19:52:45 +00004951 if (internal_status == success && db.fix_forward_references &&
4952 !db.template_param.empty() && !db.template_param.front().empty())
4953 {
4954 db.fix_forward_references = false;
4955 db.tag_templates = false;
4956 db.names.clear();
4957 db.subs.clear();
4958 demangle(mangled_name, mangled_name + len, db, internal_status);
4959 if (db.fix_forward_references)
4960 internal_status = invalid_mangled_name;
4961 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004962 if (internal_status == success)
4963 {
4964 size_t sz = db.names.back().size() + 1;
4965 if (sz > internal_size)
4966 {
4967 char* newbuf = static_cast<char*>(std::realloc(buf, sz));
4968 if (newbuf == nullptr)
4969 {
4970 internal_status = memory_alloc_failure;
4971 buf = nullptr;
4972 }
4973 else
Howard Hinnant8ad6a222013-07-26 22:14:53 +00004974 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004975 buf = newbuf;
Howard Hinnant8ad6a222013-07-26 22:14:53 +00004976 if (n != nullptr)
4977 *n = sz;
4978 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004979 }
4980 if (buf != nullptr)
4981 {
4982 db.names.back().first += db.names.back().second;
4983 std::memcpy(buf, db.names.back().first.data(), sz-1);
4984 buf[sz-1] = char(0);
4985 }
4986 }
4987 else
4988 buf = nullptr;
4989 if (status)
4990 *status = internal_status;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004991 return buf;
4992}
4993
Howard Hinnant6c33e762013-06-17 18:10:34 +00004994} // __cxxabiv1