blob: 789d57731be80a993ed2f1a6ea2e0989257f6fd0 [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
21namespace __cxxabiv1
22{
23
Howard Hinnant6c33e762013-06-17 18:10:34 +000024namespace
Howard Hinnantd213ffd2011-05-05 15:27:28 +000025{
26
Howard Hinnant6c33e762013-06-17 18:10:34 +000027enum
Howard Hinnantd213ffd2011-05-05 15:27:28 +000028{
Howard Hinnant6c33e762013-06-17 18:10:34 +000029 unknown_error = -4,
30 invalid_args = -3,
31 invalid_mangled_name,
32 memory_alloc_failure,
33 success
Howard Hinnantd213ffd2011-05-05 15:27:28 +000034};
35
Howard Hinnant6c33e762013-06-17 18:10:34 +000036template <class C>
37 const char* parse_type(const char* first, const char* last, C& db);
38template <class C>
39 const char* parse_encoding(const char* first, const char* last, C& db);
40template <class C>
Richard Smith24ecd092014-05-12 18:44:13 +000041 const char* parse_name(const char* first, const char* last, C& db,
42 bool* ends_with_template_args = 0);
Howard Hinnant6c33e762013-06-17 18:10:34 +000043template <class C>
44 const char* parse_expression(const char* first, const char* last, C& db);
45template <class C>
46 const char* parse_template_args(const char* first, const char* last, C& db);
47template <class C>
48 const char* parse_operator_name(const char* first, const char* last, C& db);
49template <class C>
50 const char* parse_unqualified_name(const char* first, const char* last, C& db);
51template <class C>
52 const char* parse_decltype(const char* first, const char* last, C& db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +000053
Howard Hinnant6c33e762013-06-17 18:10:34 +000054template <class C>
55void
56print_stack(const C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +000057{
Ed Schouten196cbd72015-03-19 09:17:21 +000058 fprintf(stderr, "---------\n");
59 fprintf(stderr, "names:\n");
Howard Hinnant6c33e762013-06-17 18:10:34 +000060 for (auto& s : db.names)
Ed Schouten196cbd72015-03-19 09:17:21 +000061 fprintf(stderr, "{%s#%s}\n", s.first.c_str(), s.second.c_str());
Howard Hinnant6c33e762013-06-17 18:10:34 +000062 int i = -1;
Ed Schouten196cbd72015-03-19 09:17:21 +000063 fprintf(stderr, "subs:\n");
Howard Hinnant6c33e762013-06-17 18:10:34 +000064 for (auto& v : db.subs)
Howard Hinnantd213ffd2011-05-05 15:27:28 +000065 {
Howard Hinnant6c33e762013-06-17 18:10:34 +000066 if (i >= 0)
Ed Schouten196cbd72015-03-19 09:17:21 +000067 fprintf(stderr, "S%i_ = {", i);
Howard Hinnant6c33e762013-06-17 18:10:34 +000068 else
Ed Schouten196cbd72015-03-19 09:17:21 +000069 fprintf(stderr, "S_ = {");
Howard Hinnant6c33e762013-06-17 18:10:34 +000070 for (auto& s : v)
Ed Schouten196cbd72015-03-19 09:17:21 +000071 fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str());
72 fprintf(stderr, "}\n");
Howard Hinnant6c33e762013-06-17 18:10:34 +000073 ++i;
Howard Hinnantd213ffd2011-05-05 15:27:28 +000074 }
Ed Schouten196cbd72015-03-19 09:17:21 +000075 fprintf(stderr, "template_param:\n");
Howard Hinnant6c33e762013-06-17 18:10:34 +000076 for (auto& t : db.template_param)
77 {
Ed Schouten196cbd72015-03-19 09:17:21 +000078 fprintf(stderr, "--\n");
Howard Hinnant6c33e762013-06-17 18:10:34 +000079 i = -1;
80 for (auto& v : t)
81 {
82 if (i >= 0)
Ed Schouten196cbd72015-03-19 09:17:21 +000083 fprintf(stderr, "T%i_ = {", i);
Howard Hinnant6c33e762013-06-17 18:10:34 +000084 else
Ed Schouten196cbd72015-03-19 09:17:21 +000085 fprintf(stderr, "T_ = {");
Howard Hinnant6c33e762013-06-17 18:10:34 +000086 for (auto& s : v)
Ed Schouten196cbd72015-03-19 09:17:21 +000087 fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str());
88 fprintf(stderr, "}\n");
Howard Hinnant6c33e762013-06-17 18:10:34 +000089 ++i;
90 }
91 }
Ed Schouten196cbd72015-03-19 09:17:21 +000092 fprintf(stderr, "---------\n\n");
Howard Hinnantd213ffd2011-05-05 15:27:28 +000093}
94
Howard Hinnant6c33e762013-06-17 18:10:34 +000095template <class C>
96void
97print_state(const char* msg, const char* first, const char* last, const C& db)
Howard Hinnant5dd173b2013-04-10 19:44:03 +000098{
Ed Schouten196cbd72015-03-19 09:17:21 +000099 fprintf(stderr, "%s: ", msg);
Howard Hinnant6c33e762013-06-17 18:10:34 +0000100 for (; first != last; ++first)
Ed Schouten196cbd72015-03-19 09:17:21 +0000101 fprintf(stderr, "%c", *first);
102 fprintf(stderr, "\n");
Howard Hinnant6c33e762013-06-17 18:10:34 +0000103 print_stack(db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000104}
105
Howard Hinnant6c33e762013-06-17 18:10:34 +0000106// <number> ::= [n] <non-negative decimal integer>
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000107
108const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +0000109parse_number(const char* first, const char* last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000110{
Howard Hinnant6c33e762013-06-17 18:10:34 +0000111 if (first != last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000112 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000113 const char* t = first;
114 if (*t == 'n')
115 ++t;
116 if (t != last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000117 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000118 if (*t == '0')
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000119 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000120 first = t+1;
121 }
122 else if ('1' <= *t && *t <= '9')
123 {
124 first = t+1;
125 while (first != last && std::isdigit(*first))
126 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000127 }
128 }
129 }
Howard Hinnant6c33e762013-06-17 18:10:34 +0000130 return first;
131}
132
133template <class Float>
134struct float_data;
135
136template <>
137struct float_data<float>
138{
139 static const size_t mangled_size = 8;
140 static const size_t max_demangled_size = 24;
Howard Hinnantc62cbea2013-06-17 20:25:21 +0000141 static constexpr const char* spec = "%af";
Howard Hinnant6c33e762013-06-17 18:10:34 +0000142};
143
144constexpr const char* float_data<float>::spec;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000145
146template <>
147struct float_data<double>
148{
149 static const size_t mangled_size = 16;
150 static const size_t max_demangled_size = 32;
151 static constexpr const char* spec = "%a";
Howard Hinnant6c33e762013-06-17 18:10:34 +0000152};
153
154constexpr const char* float_data<double>::spec;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000155
156template <>
157struct float_data<long double>
158{
Logan Chien05d51bc2014-05-10 00:42:10 +0000159#if defined(__arm__)
160 static const size_t mangled_size = 16;
161#else
Howard Hinnant6c33e762013-06-17 18:10:34 +0000162 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 +0000163#endif
Howard Hinnant6c33e762013-06-17 18:10:34 +0000164 static const size_t max_demangled_size = 40;
Howard Hinnantc62cbea2013-06-17 20:25:21 +0000165 static constexpr const char* spec = "%LaL";
Howard Hinnant6c33e762013-06-17 18:10:34 +0000166};
167
168constexpr const char* float_data<long double>::spec;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000169
170template <class Float, class C>
171const char*
172parse_floating_number(const char* first, const char* last, C& db)
173{
174 const size_t N = float_data<Float>::mangled_size;
175 if (static_cast<std::size_t>(last - first) > N)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000176 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000177 last = first + N;
178 union
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000179 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000180 Float value;
181 char buf[sizeof(Float)];
182 };
183 const char* t = first;
184 char* e = buf;
185 for (; t != last; ++t, ++e)
186 {
187 if (!isxdigit(*t))
188 return first;
189 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0') :
190 static_cast<unsigned>(*t - 'a' + 10);
191 ++t;
192 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0') :
193 static_cast<unsigned>(*t - 'a' + 10);
194 *e = static_cast<char>((d1 << 4) + d0);
195 }
196 if (*t == 'E')
197 {
198#if __LITTLE_ENDIAN__
199 std::reverse(buf, e);
200#endif
201 char num[float_data<Float>::max_demangled_size] = {0};
Howard Hinnantc62cbea2013-06-17 20:25:21 +0000202 int n = snprintf(num, sizeof(num), float_data<Float>::spec, value);
203 if (static_cast<std::size_t>(n) >= sizeof(num))
204 return first;
205 db.names.push_back(typename C::String(num, static_cast<std::size_t>(n)));
Howard Hinnant6c33e762013-06-17 18:10:34 +0000206 first = t+1;
207 }
208 }
209 return first;
210}
211
212// <source-name> ::= <positive length number> <identifier>
213
214template <class C>
215const char*
216parse_source_name(const char* first, const char* last, C& db)
217{
218 if (first != last)
219 {
220 char c = *first;
221 if (isdigit(c) && first+1 != last)
222 {
223 const char* t = first+1;
224 size_t n = static_cast<size_t>(c - '0');
225 for (c = *t; isdigit(c); c = *t)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000226 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000227 n = n * 10 + static_cast<size_t>(c - '0');
228 if (++t == last)
229 return first;
230 }
231 if (static_cast<size_t>(last - t) >= n)
232 {
233 typename C::String r(t, n);
234 if (r.substr(0, 10) == "_GLOBAL__N")
235 db.names.push_back("(anonymous namespace)");
236 else
237 db.names.push_back(std::move(r));
238 first = t + n;
239 }
240 }
241 }
242 return first;
243}
244
245// <substitution> ::= S <seq-id> _
246// ::= S_
247// <substitution> ::= Sa # ::std::allocator
248// <substitution> ::= Sb # ::std::basic_string
249// <substitution> ::= Ss # ::std::basic_string < char,
250// ::std::char_traits<char>,
251// ::std::allocator<char> >
252// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
253// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
254// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
255
256template <class C>
257const char*
258parse_substitution(const char* first, const char* last, C& db)
259{
260 if (last - first >= 2)
261 {
262 if (*first == 'S')
263 {
264 switch (first[1])
265 {
266 case 'a':
267 db.names.push_back("std::allocator");
268 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000269 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000270 case 'b':
271 db.names.push_back("std::basic_string");
272 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000273 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000274 case 's':
275 db.names.push_back("std::string");
276 first += 2;
277 break;
278 case 'i':
279 db.names.push_back("std::istream");
280 first += 2;
281 break;
282 case 'o':
283 db.names.push_back("std::ostream");
284 first += 2;
285 break;
286 case 'd':
287 db.names.push_back("std::iostream");
288 first += 2;
289 break;
290 case '_':
291 if (!db.subs.empty())
292 {
293 for (const auto& n : db.subs.front())
294 db.names.push_back(n);
295 first += 2;
296 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000297 break;
298 default:
Howard Hinnant6c33e762013-06-17 18:10:34 +0000299 if (std::isdigit(first[1]) || std::isupper(first[1]))
300 {
301 size_t sub = 0;
302 const char* t = first+1;
303 if (std::isdigit(*t))
304 sub = static_cast<size_t>(*t - '0');
305 else
306 sub = static_cast<size_t>(*t - 'A') + 10;
307 for (++t; t != last && (std::isdigit(*t) || std::isupper(*t)); ++t)
308 {
309 sub *= 36;
310 if (std::isdigit(*t))
311 sub += static_cast<size_t>(*t - '0');
312 else
313 sub += static_cast<size_t>(*t - 'A') + 10;
314 }
315 if (t == last || *t != '_')
316 return first;
317 ++sub;
318 if (sub < db.subs.size())
319 {
320 for (const auto& n : db.subs[sub])
321 db.names.push_back(n);
322 first = t+1;
323 }
324 }
325 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000326 }
327 }
328 }
329 return first;
330}
331
332// <builtin-type> ::= v # void
333// ::= w # wchar_t
334// ::= b # bool
335// ::= c # char
336// ::= a # signed char
337// ::= h # unsigned char
338// ::= s # short
339// ::= t # unsigned short
340// ::= i # int
341// ::= j # unsigned int
342// ::= l # long
343// ::= m # unsigned long
344// ::= x # long long, __int64
345// ::= y # unsigned long long, __int64
346// ::= n # __int128
347// ::= o # unsigned __int128
348// ::= f # float
349// ::= d # double
350// ::= e # long double, __float80
351// ::= g # __float128
352// ::= z # ellipsis
353// ::= Dd # IEEE 754r decimal floating point (64 bits)
354// ::= De # IEEE 754r decimal floating point (128 bits)
355// ::= Df # IEEE 754r decimal floating point (32 bits)
356// ::= Dh # IEEE 754r half-precision floating point (16 bits)
357// ::= Di # char32_t
358// ::= Ds # char16_t
359// ::= Da # auto (in dependent new-expressions)
Anders Carlsson2950e562014-02-17 21:56:01 +0000360// ::= Dc # decltype(auto)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000361// ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
362// ::= u <source-name> # vendor extended type
363
Howard Hinnant6c33e762013-06-17 18:10:34 +0000364template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000365const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +0000366parse_builtin_type(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000367{
368 if (first != last)
369 {
370 switch (*first)
371 {
372 case 'v':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000373 db.names.push_back("void");
374 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000375 break;
376 case 'w':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000377 db.names.push_back("wchar_t");
378 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000379 break;
380 case 'b':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000381 db.names.push_back("bool");
382 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000383 break;
384 case 'c':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000385 db.names.push_back("char");
386 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000387 break;
388 case 'a':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000389 db.names.push_back("signed char");
390 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000391 break;
392 case 'h':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000393 db.names.push_back("unsigned char");
394 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000395 break;
396 case 's':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000397 db.names.push_back("short");
398 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000399 break;
400 case 't':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000401 db.names.push_back("unsigned short");
402 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000403 break;
404 case 'i':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000405 db.names.push_back("int");
406 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000407 break;
408 case 'j':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000409 db.names.push_back("unsigned int");
410 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000411 break;
412 case 'l':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000413 db.names.push_back("long");
414 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000415 break;
416 case 'm':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000417 db.names.push_back("unsigned long");
418 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000419 break;
420 case 'x':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000421 db.names.push_back("long long");
422 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000423 break;
424 case 'y':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000425 db.names.push_back("unsigned long long");
426 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000427 break;
428 case 'n':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000429 db.names.push_back("__int128");
430 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000431 break;
432 case 'o':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000433 db.names.push_back("unsigned __int128");
434 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000435 break;
436 case 'f':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000437 db.names.push_back("float");
438 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000439 break;
440 case 'd':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000441 db.names.push_back("double");
442 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000443 break;
444 case 'e':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000445 db.names.push_back("long double");
446 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000447 break;
448 case 'g':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000449 db.names.push_back("__float128");
450 ++first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000451 break;
452 case 'z':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000453 db.names.push_back("...");
454 ++first;
455 break;
456 case 'u':
457 {
458 const char*t = parse_source_name(first+1, last, db);
459 if (t != first+1)
460 first = t;
461 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000462 break;
463 case 'D':
464 if (first+1 != last)
465 {
466 switch (first[1])
467 {
468 case 'd':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000469 db.names.push_back("decimal64");
470 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000471 break;
472 case 'e':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000473 db.names.push_back("decimal128");
474 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000475 break;
476 case 'f':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000477 db.names.push_back("decimal32");
478 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000479 break;
480 case 'h':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000481 db.names.push_back("decimal16");
482 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000483 break;
484 case 'i':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000485 db.names.push_back("char32_t");
486 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000487 break;
488 case 's':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000489 db.names.push_back("char16_t");
490 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000491 break;
492 case 'a':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000493 db.names.push_back("auto");
494 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000495 break;
Anders Carlsson2950e562014-02-17 21:56:01 +0000496 case 'c':
497 db.names.push_back("decltype(auto)");
498 first += 2;
499 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000500 case 'n':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000501 db.names.push_back("std::nullptr_t");
502 first += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000503 break;
504 }
505 }
506 break;
507 }
508 }
509 return first;
510}
511
Howard Hinnant6c33e762013-06-17 18:10:34 +0000512// <CV-qualifiers> ::= [r] [V] [K]
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000513
514const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +0000515parse_cv_qualifiers(const char* first, const char* last, unsigned& cv)
516{
517 cv = 0;
518 if (first != last)
519 {
520 if (*first == 'r')
521 {
522 cv |= 4;
523 ++first;
524 }
525 if (*first == 'V')
526 {
527 cv |= 2;
528 ++first;
529 }
530 if (*first == 'K')
531 {
532 cv |= 1;
533 ++first;
534 }
535 }
536 return first;
537}
538
539// <template-param> ::= T_ # first template parameter
540// ::= T <parameter-2 non-negative number> _
541
542template <class C>
543const char*
544parse_template_param(const char* first, const char* last, C& db)
545{
546 if (last - first >= 2)
547 {
548 if (*first == 'T')
549 {
550 if (first[1] == '_')
551 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000552 if (db.template_param.empty())
553 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000554 if (!db.template_param.back().empty())
555 {
556 for (auto& t : db.template_param.back().front())
557 db.names.push_back(t);
558 first += 2;
559 }
560 else
561 {
Howard Hinnantb2d1f942013-06-23 19:52:45 +0000562 db.names.push_back("T_");
Howard Hinnant6c33e762013-06-17 18:10:34 +0000563 first += 2;
564 db.fix_forward_references = true;
565 }
566 }
567 else if (isdigit(first[1]))
568 {
569 const char* t = first+1;
570 size_t sub = static_cast<size_t>(*t - '0');
571 for (++t; t != last && isdigit(*t); ++t)
572 {
573 sub *= 10;
574 sub += static_cast<size_t>(*t - '0');
575 }
Howard Hinnant753a30d2013-12-11 19:44:25 +0000576 if (t == last || *t != '_' || db.template_param.empty())
Howard Hinnant6c33e762013-06-17 18:10:34 +0000577 return first;
578 ++sub;
579 if (sub < db.template_param.back().size())
580 {
581 for (auto& temp : db.template_param.back()[sub])
582 db.names.push_back(temp);
583 first = t+1;
584 }
585 else
586 {
Howard Hinnantb2d1f942013-06-23 19:52:45 +0000587 db.names.push_back(typename C::String(first, t+1));
Howard Hinnant6c33e762013-06-17 18:10:34 +0000588 first = t+1;
589 db.fix_forward_references = true;
590 }
591 }
592 }
593 }
594 return first;
595}
596
597// cc <type> <expression> # const_cast<type> (expression)
598
599template <class C>
600const char*
601parse_const_cast_expr(const char* first, const char* last, C& db)
602{
603 if (last - first >= 3 && first[0] == 'c' && first[1] == 'c')
604 {
605 const char* t = parse_type(first+2, last, db);
606 if (t != first+2)
607 {
608 const char* t1 = parse_expression(t, last, db);
609 if (t1 != t)
610 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000611 if (db.names.size() < 2)
612 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000613 auto expr = db.names.back().move_full();
614 db.names.pop_back();
615 db.names.back() = "const_cast<" + db.names.back().move_full() + ">(" + expr + ")";
616 first = t1;
617 }
618 }
619 }
620 return first;
621}
622
623// dc <type> <expression> # dynamic_cast<type> (expression)
624
625template <class C>
626const char*
627parse_dynamic_cast_expr(const char* first, const char* last, C& db)
628{
629 if (last - first >= 3 && first[0] == 'd' && first[1] == 'c')
630 {
631 const char* t = parse_type(first+2, last, db);
632 if (t != first+2)
633 {
634 const char* t1 = parse_expression(t, last, db);
635 if (t1 != t)
636 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000637 if (db.names.size() < 2)
638 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000639 auto expr = db.names.back().move_full();
640 db.names.pop_back();
641 db.names.back() = "dynamic_cast<" + db.names.back().move_full() + ">(" + expr + ")";
642 first = t1;
643 }
644 }
645 }
646 return first;
647}
648
649// rc <type> <expression> # reinterpret_cast<type> (expression)
650
651template <class C>
652const char*
653parse_reinterpret_cast_expr(const char* first, const char* last, C& db)
654{
655 if (last - first >= 3 && first[0] == 'r' && first[1] == 'c')
656 {
657 const char* t = parse_type(first+2, last, db);
658 if (t != first+2)
659 {
660 const char* t1 = parse_expression(t, last, db);
661 if (t1 != t)
662 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000663 if (db.names.size() < 2)
664 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000665 auto expr = db.names.back().move_full();
666 db.names.pop_back();
667 db.names.back() = "reinterpret_cast<" + db.names.back().move_full() + ">(" + expr + ")";
668 first = t1;
669 }
670 }
671 }
672 return first;
673}
674
675// sc <type> <expression> # static_cast<type> (expression)
676
677template <class C>
678const char*
679parse_static_cast_expr(const char* first, const char* last, C& db)
680{
681 if (last - first >= 3 && first[0] == 's' && first[1] == 'c')
682 {
683 const char* t = parse_type(first+2, last, db);
684 if (t != first+2)
685 {
686 const char* t1 = parse_expression(t, last, db);
687 if (t1 != t)
688 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000689 if (db.names.size() < 2)
690 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000691 auto expr = db.names.back().move_full();
692 db.names.pop_back();
693 db.names.back() = "static_cast<" + db.names.back().move_full() + ">(" + expr + ")";
694 first = t1;
695 }
696 }
697 }
698 return first;
699}
700
701// sp <expression> # pack expansion
702
703template <class C>
704const char*
705parse_pack_expansion(const char* first, const char* last, C& db)
706{
707 if (last - first >= 3 && first[0] == 's' && first[1] == 'p')
708 {
709 const char* t = parse_expression(first+2, last, db);
710 if (t != first+2)
711 first = t;
712 }
713 return first;
714}
715
716// st <type> # sizeof (a type)
717
718template <class C>
719const char*
720parse_sizeof_type_expr(const char* first, const char* last, C& db)
721{
722 if (last - first >= 3 && first[0] == 's' && first[1] == 't')
723 {
724 const char* t = parse_type(first+2, last, db);
725 if (t != first+2)
726 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000727 if (db.names.empty())
728 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000729 db.names.back() = "sizeof (" + db.names.back().move_full() + ")";
730 first = t;
731 }
732 }
733 return first;
734}
735
736// sz <expr> # sizeof (a expression)
737
738template <class C>
739const char*
740parse_sizeof_expr_expr(const char* first, const char* last, C& db)
741{
742 if (last - first >= 3 && first[0] == 's' && first[1] == 'z')
743 {
744 const char* t = parse_expression(first+2, last, db);
745 if (t != first+2)
746 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000747 if (db.names.empty())
748 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000749 db.names.back() = "sizeof (" + db.names.back().move_full() + ")";
750 first = t;
751 }
752 }
753 return first;
754}
755
756// sZ <template-param> # size of a parameter pack
757
758template <class C>
759const char*
760parse_sizeof_param_pack_expr(const char* first, const char* last, C& db)
761{
762 if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' && first[2] == 'T')
763 {
764 size_t k0 = db.names.size();
765 const char* t = parse_template_param(first+2, last, db);
766 size_t k1 = db.names.size();
767 if (t != first+2)
768 {
769 typename C::String tmp("sizeof...(");
770 size_t k = k0;
771 if (k != k1)
772 {
773 tmp += db.names[k].move_full();
774 for (++k; k != k1; ++k)
775 tmp += ", " + db.names[k].move_full();
776 }
777 tmp += ")";
778 for (; k1 != k0; --k1)
779 db.names.pop_back();
780 db.names.push_back(std::move(tmp));
781 first = t;
782 }
783 }
784 return first;
785}
786
787// <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, first parameter
788// ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
789// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _ # L > 0, first parameter
790// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
791
792template <class C>
793const char*
794parse_function_param(const char* first, const char* last, C& db)
795{
796 if (last - first >= 3 && *first == 'f')
797 {
798 if (first[1] == 'p')
799 {
800 unsigned cv;
801 const char* t = parse_cv_qualifiers(first+2, last, cv);
802 const char* t1 = parse_number(t, last);
803 if (t1 != last && *t1 == '_')
804 {
805 db.names.push_back("fp" + typename C::String(t, t1));
806 first = t1+1;
807 }
808 }
809 else if (first[1] == 'L')
810 {
811 unsigned cv;
812 const char* t0 = parse_number(first+2, last);
813 if (t0 != last && *t0 == 'p')
814 {
815 ++t0;
816 const char* t = parse_cv_qualifiers(t0, last, cv);
817 const char* t1 = parse_number(t, last);
818 if (t1 != last && *t1 == '_')
819 {
820 db.names.push_back("fp" + typename C::String(t, t1));
821 first = t1+1;
822 }
823 }
824 }
825 }
826 return first;
827}
828
829// sZ <function-param> # size of a function parameter pack
830
831template <class C>
832const char*
833parse_sizeof_function_param_pack_expr(const char* first, const char* last, C& db)
834{
835 if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' && first[2] == 'f')
836 {
837 const char* t = parse_function_param(first+2, last, db);
838 if (t != first+2)
839 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000840 if (db.names.empty())
841 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000842 db.names.back() = "sizeof...(" + db.names.back().move_full() + ")";
843 first = t;
844 }
845 }
846 return first;
847}
848
849// te <expression> # typeid (expression)
850// ti <type> # typeid (type)
851
852template <class C>
853const char*
854parse_typeid_expr(const char* first, const char* last, C& db)
855{
856 if (last - first >= 3 && first[0] == 't' && (first[1] == 'e' || first[1] == 'i'))
857 {
858 const char* t;
859 if (first[1] == 'e')
860 t = parse_expression(first+2, last, db);
861 else
862 t = parse_type(first+2, last, db);
863 if (t != first+2)
864 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000865 if (db.names.empty())
866 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000867 db.names.back() = "typeid(" + db.names.back().move_full() + ")";
868 first = t;
869 }
870 }
871 return first;
872}
873
874// tw <expression> # throw expression
875
876template <class C>
877const char*
878parse_throw_expr(const char* first, const char* last, C& db)
879{
880 if (last - first >= 3 && first[0] == 't' && first[1] == 'w')
881 {
882 const char* t = parse_expression(first+2, last, db);
883 if (t != first+2)
884 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000885 if (db.names.empty())
886 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000887 db.names.back() = "throw " + db.names.back().move_full();
888 first = t;
889 }
890 }
891 return first;
892}
893
894// ds <expression> <expression> # expr.*expr
895
896template <class C>
897const char*
898parse_dot_star_expr(const char* first, const char* last, C& db)
899{
900 if (last - first >= 3 && first[0] == 'd' && first[1] == 's')
901 {
902 const char* t = parse_expression(first+2, last, db);
903 if (t != first+2)
904 {
905 const char* t1 = parse_expression(t, last, db);
906 if (t1 != t)
907 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000908 if (db.names.size() < 2)
909 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000910 auto expr = db.names.back().move_full();
911 db.names.pop_back();
912 db.names.back().first += ".*" + expr;
913 first = t1;
914 }
915 }
916 }
917 return first;
918}
919
920// <simple-id> ::= <source-name> [ <template-args> ]
921
922template <class C>
923const char*
924parse_simple_id(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000925{
926 if (first != last)
927 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000928 const char* t = parse_source_name(first, last, db);
929 if (t != first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000930 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000931 const char* t1 = parse_template_args(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000932 if (t1 != t)
933 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000934 if (db.names.size() < 2)
935 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000936 auto args = db.names.back().move_full();
937 db.names.pop_back();
938 db.names.back().first += std::move(args);
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000939 }
Howard Hinnant6c33e762013-06-17 18:10:34 +0000940 first = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000941 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000942 else
Howard Hinnant6c33e762013-06-17 18:10:34 +0000943 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000944 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000945 return first;
946}
947
Howard Hinnant6c33e762013-06-17 18:10:34 +0000948// <unresolved-type> ::= <template-param>
949// ::= <decltype>
950// ::= <substitution>
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000951
Howard Hinnant6c33e762013-06-17 18:10:34 +0000952template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000953const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +0000954parse_unresolved_type(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000955{
Howard Hinnant6c33e762013-06-17 18:10:34 +0000956 if (first != last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000957 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000958 const char* t = first;
959 switch (*first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000960 {
Howard Hinnant86ccacd2012-09-13 23:49:59 +0000961 case 'T':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000962 {
963 size_t k0 = db.names.size();
964 t = parse_template_param(first, last, db);
965 size_t k1 = db.names.size();
966 if (t != first && k1 == k0 + 1)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000967 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000968 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
969 first = t;
Howard Hinnantab039992012-08-01 18:56:46 +0000970 }
971 else
Howard Hinnant342f2f92012-11-30 18:43:50 +0000972 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000973 for (; k1 != k0; --k1)
974 db.names.pop_back();
Howard Hinnant342f2f92012-11-30 18:43:50 +0000975 }
Howard Hinnantab87dcf2011-12-15 20:02:15 +0000976 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000977 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000978 case 'D':
Howard Hinnant6c33e762013-06-17 18:10:34 +0000979 t = parse_decltype(first, last, db);
980 if (t != first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000981 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000982 if (db.names.empty())
983 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000984 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
985 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000986 }
987 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +0000988 case 'S':
989 t = parse_substitution(first, last, db);
990 if (t != first)
991 first = t;
992 else
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000993 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000994 if (last - first > 2 && first[1] == 't')
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000995 {
Howard Hinnant6c33e762013-06-17 18:10:34 +0000996 t = parse_unqualified_name(first+2, last, db);
997 if (t != first+2)
Howard Hinnantd213ffd2011-05-05 15:27:28 +0000998 {
Howard Hinnant753a30d2013-12-11 19:44:25 +0000999 if (db.names.empty())
1000 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001001 db.names.back().first.insert(0, "std::");
1002 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
1003 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001004 }
1005 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001006 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001007 break;
1008 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001009 }
1010 return first;
1011}
1012
1013// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
1014// ::= <simple-id> # e.g., ~A<2*N>
1015
Howard Hinnant6c33e762013-06-17 18:10:34 +00001016template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001017const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001018parse_destructor_name(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001019{
1020 if (first != last)
1021 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001022 const char* t = parse_unresolved_type(first, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001023 if (t == first)
Howard Hinnant6c33e762013-06-17 18:10:34 +00001024 t = parse_simple_id(first, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001025 if (t != first)
Howard Hinnant6c33e762013-06-17 18:10:34 +00001026 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001027 if (db.names.empty())
1028 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001029 db.names.back().first.insert(0, "~");
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001030 first = t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001031 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001032 }
1033 return first;
1034}
1035
1036// <base-unresolved-name> ::= <simple-id> # unresolved name
1037// extension ::= <operator-name> # unresolved operator-function-id
1038// extension ::= <operator-name> <template-args> # unresolved operator template-id
1039// ::= on <operator-name> # unresolved operator-function-id
1040// ::= on <operator-name> <template-args> # unresolved operator template-id
1041// ::= dn <destructor-name> # destructor or pseudo-destructor;
1042// # e.g. ~X or ~X<N-1>
1043
Howard Hinnant6c33e762013-06-17 18:10:34 +00001044template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001045const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001046parse_base_unresolved_name(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001047{
1048 if (last - first >= 2)
1049 {
1050 if ((first[0] == 'o' || first[0] == 'd') && first[1] == 'n')
1051 {
1052 if (first[0] == 'o')
1053 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001054 const char* t = parse_operator_name(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001055 if (t != first+2)
Howard Hinnant6c33e762013-06-17 18:10:34 +00001056 {
1057 first = parse_template_args(t, last, db);
1058 if (first != t)
1059 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001060 if (db.names.size() < 2)
1061 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001062 auto args = db.names.back().move_full();
1063 db.names.pop_back();
1064 db.names.back().first += std::move(args);
1065 }
1066 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001067 }
1068 else
1069 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001070 const char* t = parse_destructor_name(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001071 if (t != first+2)
1072 first = t;
1073 }
1074 }
1075 else
1076 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001077 const char* t = parse_simple_id(first, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001078 if (t == first)
1079 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001080 t = parse_operator_name(first, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001081 if (t != first)
Howard Hinnant6c33e762013-06-17 18:10:34 +00001082 {
1083 first = parse_template_args(t, last, db);
1084 if (first != t)
1085 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001086 if (db.names.size() < 2)
1087 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001088 auto args = db.names.back().move_full();
1089 db.names.pop_back();
1090 db.names.back().first += std::move(args);
1091 }
1092 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001093 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001094 else
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001095 first = t;
1096 }
1097 }
1098 return first;
1099}
1100
Howard Hinnant6c33e762013-06-17 18:10:34 +00001101// <unresolved-qualifier-level> ::= <simple-id>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001102
Howard Hinnant6c33e762013-06-17 18:10:34 +00001103template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001104const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001105parse_unresolved_qualifier_level(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001106{
Howard Hinnant6c33e762013-06-17 18:10:34 +00001107 return parse_simple_id(first, last, db);
Howard Hinnant889b02d2011-06-22 19:27:39 +00001108}
1109
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001110// <unresolved-name>
Howard Hinnant889b02d2011-06-22 19:27:39 +00001111// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001112// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
1113// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
1114// # A::x, N::y, A<T>::z; "gs" means leading "::"
Howard Hinnant889b02d2011-06-22 19:27:39 +00001115// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
Howard Hinnant6c33e762013-06-17 18:10:34 +00001116// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
Howard Hinnant889b02d2011-06-22 19:27:39 +00001117// # T::N::x /decltype(p)::N::x
1118// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001119
Howard Hinnant6c33e762013-06-17 18:10:34 +00001120template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001121const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001122parse_unresolved_name(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001123{
1124 if (last - first > 2)
1125 {
Howard Hinnant889b02d2011-06-22 19:27:39 +00001126 const char* t = first;
1127 bool global = false;
1128 if (t[0] == 'g' && t[1] == 's')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001129 {
Howard Hinnant889b02d2011-06-22 19:27:39 +00001130 global = true;
1131 t += 2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001132 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001133 const char* t2 = parse_base_unresolved_name(t, last, db);
Howard Hinnant889b02d2011-06-22 19:27:39 +00001134 if (t2 != t)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001135 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001136 if (global)
Howard Hinnant753a30d2013-12-11 19:44:25 +00001137 {
1138 if (db.names.empty())
1139 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001140 db.names.back().first.insert(0, "::");
Howard Hinnant753a30d2013-12-11 19:44:25 +00001141 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001142 first = t2;
Howard Hinnant889b02d2011-06-22 19:27:39 +00001143 }
1144 else if (last - t > 2 && t[0] == 's' && t[1] == 'r')
1145 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001146 if (t[2] == 'N')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001147 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001148 t += 3;
1149 const char* t1 = parse_unresolved_type(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001150 if (t1 == t || t1 == last)
1151 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001152 t = t1;
1153 t1 = parse_template_args(t, last, db);
1154 if (t1 != t)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001155 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001156 if (db.names.size() < 2)
1157 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001158 auto args = db.names.back().move_full();
1159 db.names.pop_back();
1160 db.names.back().first += std::move(args);
1161 t = t1;
1162 if (t == last)
1163 {
1164 db.names.pop_back();
1165 return first;
1166 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001167 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001168 while (*t != 'E')
1169 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001170 t1 = parse_unresolved_qualifier_level(t, last, db);
Howard Hinnant753a30d2013-12-11 19:44:25 +00001171 if (t1 == t || t1 == last || db.names.size() < 2)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001172 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001173 auto s = db.names.back().move_full();
1174 db.names.pop_back();
1175 db.names.back().first += "::" + std::move(s);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001176 t = t1;
1177 }
1178 ++t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001179 t1 = parse_base_unresolved_name(t, last, db);
1180 if (t1 == t)
1181 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001182 if (!db.names.empty())
1183 db.names.pop_back();
Howard Hinnant6c33e762013-06-17 18:10:34 +00001184 return first;
1185 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00001186 if (db.names.size() < 2)
1187 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001188 auto s = db.names.back().move_full();
1189 db.names.pop_back();
1190 db.names.back().first += "::" + std::move(s);
1191 first = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001192 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001193 else
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001194 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001195 t += 2;
1196 const char* t1 = parse_unresolved_type(t, last, db);
1197 if (t1 != t)
1198 {
1199 t = t1;
1200 t1 = parse_template_args(t, last, db);
1201 if (t1 != t)
1202 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001203 if (db.names.size() < 2)
1204 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001205 auto args = db.names.back().move_full();
1206 db.names.pop_back();
1207 db.names.back().first += std::move(args);
1208 t = t1;
1209 }
1210 t1 = parse_base_unresolved_name(t, last, db);
1211 if (t1 == t)
1212 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001213 if (!db.names.empty())
1214 db.names.pop_back();
Howard Hinnant6c33e762013-06-17 18:10:34 +00001215 return first;
1216 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00001217 if (db.names.size() < 2)
1218 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001219 auto s = db.names.back().move_full();
1220 db.names.pop_back();
1221 db.names.back().first += "::" + std::move(s);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001222 first = t1;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001223 }
1224 else
1225 {
1226 t1 = parse_unresolved_qualifier_level(t, last, db);
1227 if (t1 == t || t1 == last)
1228 return first;
1229 t = t1;
1230 if (global)
Howard Hinnant753a30d2013-12-11 19:44:25 +00001231 {
1232 if (db.names.empty())
1233 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001234 db.names.back().first.insert(0, "::");
Howard Hinnant753a30d2013-12-11 19:44:25 +00001235 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001236 while (*t != 'E')
1237 {
1238 t1 = parse_unresolved_qualifier_level(t, last, db);
Howard Hinnant753a30d2013-12-11 19:44:25 +00001239 if (t1 == t || t1 == last || db.names.size() < 2)
Howard Hinnant6c33e762013-06-17 18:10:34 +00001240 return first;
1241 auto s = db.names.back().move_full();
1242 db.names.pop_back();
1243 db.names.back().first += "::" + std::move(s);
1244 t = t1;
1245 }
1246 ++t;
1247 t1 = parse_base_unresolved_name(t, last, db);
1248 if (t1 == t)
1249 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001250 if (!db.names.empty())
1251 db.names.pop_back();
Howard Hinnant6c33e762013-06-17 18:10:34 +00001252 return first;
1253 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00001254 if (db.names.size() < 2)
1255 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001256 auto s = db.names.back().move_full();
1257 db.names.pop_back();
1258 db.names.back().first += "::" + std::move(s);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001259 first = t1;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001260 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001261 }
1262 }
1263 }
1264 return first;
1265}
1266
1267// dt <expression> <unresolved-name> # expr.name
1268
Howard Hinnant6c33e762013-06-17 18:10:34 +00001269template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001270const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001271parse_dot_expr(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001272{
1273 if (last - first >= 3 && first[0] == 'd' && first[1] == 't')
1274 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001275 const char* t = parse_expression(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001276 if (t != first+2)
1277 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001278 const char* t1 = parse_unresolved_name(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001279 if (t1 != t)
1280 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001281 if (db.names.size() < 2)
1282 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001283 auto name = db.names.back().move_full();
1284 db.names.pop_back();
1285 db.names.back().first += "." + name;
1286 first = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001287 }
1288 }
1289 }
1290 return first;
1291}
1292
Howard Hinnant6c33e762013-06-17 18:10:34 +00001293// cl <expression>+ E # call
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001294
Howard Hinnant6c33e762013-06-17 18:10:34 +00001295template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001296const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001297parse_call_expr(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001298{
Howard Hinnant6c33e762013-06-17 18:10:34 +00001299 if (last - first >= 4 && first[0] == 'c' && first[1] == 'l')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001300 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001301 const char* t = parse_expression(first+2, last, db);
1302 if (t != first+2)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001303 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001304 if (t == last)
1305 return first;
Howard Hinnant753a30d2013-12-11 19:44:25 +00001306 if (db.names.empty())
1307 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001308 db.names.back().first += db.names.back().second;
1309 db.names.back().second = typename C::String();
1310 db.names.back().first.append("(");
1311 bool first_expr = true;
1312 while (*t != 'E')
1313 {
1314 const char* t1 = parse_expression(t, last, db);
1315 if (t1 == t || t1 == last)
1316 return first;
Howard Hinnant753a30d2013-12-11 19:44:25 +00001317 if (db.names.empty())
1318 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001319 auto tmp = db.names.back().move_full();
1320 db.names.pop_back();
1321 if (!tmp.empty())
1322 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001323 if (db.names.empty())
1324 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001325 if (!first_expr)
1326 {
1327 db.names.back().first.append(", ");
1328 first_expr = false;
1329 }
1330 db.names.back().first.append(tmp);
1331 }
1332 t = t1;
1333 }
1334 ++t;
Howard Hinnant753a30d2013-12-11 19:44:25 +00001335 if (db.names.empty())
1336 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001337 db.names.back().first.append(")");
1338 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001339 }
1340 }
1341 return first;
1342}
1343
1344// [gs] nw <expression>* _ <type> E # new (expr-list) type
1345// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
1346// [gs] na <expression>* _ <type> E # new[] (expr-list) type
1347// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1348// <initializer> ::= pi <expression>* E # parenthesized initialization
1349
Howard Hinnant6c33e762013-06-17 18:10:34 +00001350template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001351const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001352parse_new_expr(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001353{
1354 if (last - first >= 4)
1355 {
1356 const char* t = first;
1357 bool parsed_gs = false;
1358 if (t[0] == 'g' && t[1] == 's')
1359 {
1360 t += 2;
1361 parsed_gs = true;
1362 }
1363 if (t[0] == 'n' && (t[1] == 'w' || t[1] == 'a'))
1364 {
1365 bool is_array = t[1] == 'a';
1366 t += 2;
1367 if (t == last)
1368 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001369 bool has_expr_list = false;
1370 bool first_expr = true;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001371 while (*t != '_')
1372 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001373 const char* t1 = parse_expression(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001374 if (t1 == t || t1 == last)
1375 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001376 has_expr_list = true;
1377 if (!first_expr)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001378 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001379 if (db.names.empty())
1380 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001381 auto tmp = db.names.back().move_full();
1382 db.names.pop_back();
1383 if (!tmp.empty())
1384 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001385 if (db.names.empty())
1386 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001387 db.names.back().first.append(", ");
1388 db.names.back().first.append(tmp);
1389 first_expr = false;
1390 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001391 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001392 t = t1;
1393 }
1394 ++t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001395 const char* t1 = parse_type(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001396 if (t1 == t || t1 == last)
1397 return first;
1398 t = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001399 bool has_init = false;
1400 if (last - t >= 3 && t[0] == 'p' && t[1] == 'i')
1401 {
1402 t += 2;
1403 has_init = true;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001404 first_expr = true;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001405 while (*t != 'E')
1406 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001407 t1 = parse_expression(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001408 if (t1 == t || t1 == last)
1409 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001410 if (!first_expr)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001411 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001412 if (db.names.empty())
1413 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001414 auto tmp = db.names.back().move_full();
1415 db.names.pop_back();
1416 if (!tmp.empty())
1417 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001418 if (db.names.empty())
1419 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001420 db.names.back().first.append(", ");
1421 db.names.back().first.append(tmp);
1422 first_expr = false;
1423 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001424 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001425 t = t1;
1426 }
1427 }
1428 if (*t != 'E')
1429 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001430 typename C::String init_list;
1431 if (has_init)
1432 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001433 if (db.names.empty())
1434 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001435 init_list = db.names.back().move_full();
1436 db.names.pop_back();
1437 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00001438 if (db.names.empty())
1439 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001440 auto type = db.names.back().move_full();
1441 db.names.pop_back();
1442 typename C::String expr_list;
1443 if (has_expr_list)
1444 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001445 if (db.names.empty())
1446 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001447 expr_list = db.names.back().move_full();
1448 db.names.pop_back();
1449 }
1450 typename C::String r;
1451 if (parsed_gs)
1452 r = "::";
1453 if (is_array)
1454 r += "[] ";
1455 else
1456 r += " ";
1457 if (has_expr_list)
1458 r += "(" + expr_list + ") ";
1459 r += type;
1460 if (has_init)
1461 r += " (" + init_list + ")";
1462 db.names.push_back(std::move(r));
1463 first = t+1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001464 }
1465 }
1466 return first;
1467}
1468
Howard Hinnant6c33e762013-06-17 18:10:34 +00001469// cv <type> <expression> # conversion with one argument
1470// cv <type> _ <expression>* E # conversion with a different number of arguments
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001471
Howard Hinnant6c33e762013-06-17 18:10:34 +00001472template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001473const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001474parse_conversion_expr(const char* first, const char* last, C& db)
1475{
1476 if (last - first >= 3 && first[0] == 'c' && first[1] == 'v')
1477 {
1478 bool try_to_parse_template_args = db.try_to_parse_template_args;
1479 db.try_to_parse_template_args = false;
1480 const char* t = parse_type(first+2, last, db);
1481 db.try_to_parse_template_args = try_to_parse_template_args;
1482 if (t != first+2 && t != last)
1483 {
1484 if (*t != '_')
1485 {
1486 const char* t1 = parse_expression(t, last, db);
1487 if (t1 == t)
1488 return first;
1489 t = t1;
1490 }
1491 else
1492 {
1493 ++t;
1494 if (t == last)
1495 return first;
1496 if (*t == 'E')
1497 db.names.emplace_back();
1498 else
1499 {
1500 bool first_expr = true;
1501 while (*t != 'E')
1502 {
1503 const char* t1 = parse_expression(t, last, db);
1504 if (t1 == t || t1 == last)
1505 return first;
1506 if (!first_expr)
1507 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001508 if (db.names.empty())
1509 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001510 auto tmp = db.names.back().move_full();
1511 db.names.pop_back();
1512 if (!tmp.empty())
1513 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001514 if (db.names.empty())
1515 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001516 db.names.back().first.append(", ");
1517 db.names.back().first.append(tmp);
1518 first_expr = false;
1519 }
1520 }
1521 t = t1;
1522 }
1523 }
1524 ++t;
1525 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00001526 if (db.names.size() < 2)
1527 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001528 auto tmp = db.names.back().move_full();
1529 db.names.pop_back();
1530 db.names.back() = "(" + db.names.back().move_full() + ")(" + tmp + ")";
1531 first = t;
1532 }
1533 }
1534 return first;
1535}
1536
1537// pt <expression> <expression> # expr->name
1538
1539template <class C>
1540const char*
1541parse_arrow_expr(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001542{
1543 if (last - first >= 3 && first[0] == 'p' && first[1] == 't')
1544 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001545 const char* t = parse_expression(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001546 if (t != first+2)
1547 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001548 const char* t1 = parse_expression(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001549 if (t1 != t)
1550 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001551 if (db.names.size() < 2)
1552 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001553 auto tmp = db.names.back().move_full();
1554 db.names.pop_back();
1555 db.names.back().first += "->";
1556 db.names.back().first += tmp;
1557 first = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001558 }
1559 }
1560 }
1561 return first;
1562}
1563
Howard Hinnant6c33e762013-06-17 18:10:34 +00001564// <ref-qualifier> ::= R # & ref-qualifier
1565// <ref-qualifier> ::= O # && ref-qualifier
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001566
Howard Hinnant6c33e762013-06-17 18:10:34 +00001567// <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
1568
1569template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001570const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001571parse_function_type(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001572{
Howard Hinnant6c33e762013-06-17 18:10:34 +00001573 if (first != last && *first == 'F')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001574 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001575 const char* t = first+1;
1576 if (t != last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001577 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001578 bool externC = false;
1579 if (*t == 'Y')
1580 {
1581 externC = true;
1582 if (++t == last)
1583 return first;
1584 }
1585 const char* t1 = parse_type(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001586 if (t1 != t)
1587 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001588 t = t1;
1589 typename C::String sig("(");
1590 int ref_qual = 0;
1591 while (true)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001592 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001593 if (t == last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001594 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001595 db.names.pop_back();
1596 return first;
1597 }
1598 if (*t == 'E')
1599 {
1600 ++t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001601 break;
1602 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001603 if (*t == 'v')
1604 {
1605 ++t;
1606 continue;
1607 }
1608 if (*t == 'R' && t+1 != last && t[1] == 'E')
1609 {
1610 ref_qual = 1;
1611 ++t;
1612 continue;
1613 }
1614 if (*t == 'O' && t+1 != last && t[1] == 'E')
1615 {
1616 ref_qual = 2;
1617 ++t;
1618 continue;
1619 }
1620 size_t k0 = db.names.size();
1621 t1 = parse_type(t, last, db);
1622 size_t k1 = db.names.size();
1623 if (t1 == t || t1 == last)
1624 return first;
1625 for (size_t k = k0; k < k1; ++k)
1626 {
1627 if (sig.size() > 1)
1628 sig += ", ";
1629 sig += db.names[k].move_full();
1630 }
1631 for (size_t k = k0; k < k1; ++k)
1632 db.names.pop_back();
1633 t = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001634 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001635 sig += ")";
1636 switch (ref_qual)
1637 {
1638 case 1:
1639 sig += " &";
1640 break;
1641 case 2:
1642 sig += " &&";
1643 break;
1644 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00001645 if (db.names.empty())
1646 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001647 db.names.back().first += " ";
1648 db.names.back().second.insert(0, sig);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001649 first = t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001650 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001651 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001652 }
1653 return first;
1654}
1655
1656// <pointer-to-member-type> ::= M <class type> <member type>
1657
1658template <class C>
1659const char*
1660parse_pointer_to_member_type(const char* first, const char* last, C& db)
1661{
1662 if (first != last && *first == 'M')
1663 {
1664 const char* t = parse_type(first+1, last, db);
1665 if (t != first+1)
1666 {
1667 const char* t2 = parse_type(t, last, db);
1668 if (t2 != t)
1669 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001670 if (db.names.size() < 2)
1671 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001672 auto func = std::move(db.names.back());
1673 db.names.pop_back();
1674 auto class_type = std::move(db.names.back());
1675 if (func.second.front() == '(')
1676 {
1677 db.names.back().first = std::move(func.first) + "(" + class_type.move_full() + "::*";
1678 db.names.back().second = ")" + std::move(func.second);
1679 }
1680 else
1681 {
1682 db.names.back().first = std::move(func.first) + " " + class_type.move_full() + "::*";
1683 db.names.back().second = std::move(func.second);
1684 }
1685 first = t2;
1686 }
1687 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001688 }
1689 return first;
1690}
1691
1692// <array-type> ::= A <positive dimension number> _ <element type>
1693// ::= A [<dimension expression>] _ <element type>
1694
Howard Hinnant6c33e762013-06-17 18:10:34 +00001695template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001696const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001697parse_array_type(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001698{
1699 if (first != last && *first == 'A' && first+1 != last)
1700 {
1701 if (first[1] == '_')
1702 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001703 const char* t = parse_type(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001704 if (t != first+2)
1705 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001706 if (db.names.empty())
1707 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001708 if (db.names.back().second.substr(0, 2) == " [")
1709 db.names.back().second.erase(0, 1);
1710 db.names.back().second.insert(0, " []");
1711 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001712 }
1713 }
1714 else if ('1' <= first[1] && first[1] <= '9')
1715 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001716 const char* t = parse_number(first+1, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001717 if (t != last && *t == '_')
1718 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001719 const char* t2 = parse_type(t+1, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001720 if (t2 != t+1)
1721 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001722 if (db.names.empty())
1723 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001724 if (db.names.back().second.substr(0, 2) == " [")
1725 db.names.back().second.erase(0, 1);
1726 db.names.back().second.insert(0, " [" + typename C::String(first+1, t) + "]");
1727 first = t2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001728 }
1729 }
1730 }
1731 else
1732 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001733 const char* t = parse_expression(first+1, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001734 if (t != first+1 && t != last && *t == '_')
1735 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001736 const char* t2 = parse_type(++t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001737 if (t2 != t)
1738 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001739 if (db.names.size() < 2)
1740 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001741 auto type = std::move(db.names.back());
1742 db.names.pop_back();
1743 auto expr = std::move(db.names.back());
1744 db.names.back().first = std::move(type.first);
1745 if (type.second.substr(0, 2) == " [")
1746 type.second.erase(0, 1);
1747 db.names.back().second = " [" + expr.move_full() + "]" + std::move(type.second);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001748 first = t2;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001749 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001750 }
1751 }
1752 }
1753 return first;
1754}
1755
1756// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
1757// ::= DT <expression> E # decltype of an expression (C++0x)
1758
Howard Hinnant6c33e762013-06-17 18:10:34 +00001759template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001760const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001761parse_decltype(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001762{
1763 if (last - first >= 4 && first[0] == 'D')
1764 {
1765 switch (first[1])
1766 {
1767 case 't':
1768 case 'T':
1769 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001770 const char* t = parse_expression(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001771 if (t != first+2 && t != last && *t == 'E')
1772 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001773 if (db.names.empty())
1774 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001775 db.names.back() = "decltype(" + db.names.back().move_full() + ")";
1776 first = t+1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001777 }
1778 }
1779 break;
1780 }
1781 }
1782 return first;
1783}
1784
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001785// extension:
1786// <vector-type> ::= Dv <positive dimension number> _
1787// <extended element type>
1788// ::= Dv [<dimension expression>] _ <element type>
1789// <extended element type> ::= <element type>
1790// ::= p # AltiVec vector pixel
1791
Howard Hinnant6c33e762013-06-17 18:10:34 +00001792template <class C>
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001793const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001794parse_vector_type(const char* first, const char* last, C& db)
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001795{
1796 if (last - first > 3 && first[0] == 'D' && first[1] == 'v')
1797 {
1798 if ('1' <= first[2] && first[2] <= '9')
1799 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001800 const char* t = parse_number(first+2, last);
1801 if (t == last || *t != '_')
1802 return first;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001803 const char* num = first + 2;
Howard Hinnant3e5c7d02012-03-08 18:45:24 +00001804 size_t sz = static_cast<size_t>(t - num);
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001805 if (++t != last)
1806 {
1807 if (*t != 'p')
1808 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001809 const char* t1 = parse_type(t, last, db);
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001810 if (t1 != t)
1811 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001812 if (db.names.empty())
1813 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001814 db.names.back().first += " vector[" + typename C::String(num, sz) + "]";
1815 first = t1;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001816 }
1817 }
1818 else
1819 {
1820 ++t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001821 db.names.push_back("pixel vector[" + typename C::String(num, sz) + "]");
1822 first = t;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001823 }
1824 }
1825 }
1826 else
1827 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001828 typename C::String num;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001829 const char* t1 = first+2;
1830 if (*t1 != '_')
1831 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001832 const char* t = parse_expression(t1, last, db);
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001833 if (t != t1)
Howard Hinnant6c33e762013-06-17 18:10:34 +00001834 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001835 if (db.names.empty())
1836 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001837 num = db.names.back().move_full();
1838 db.names.pop_back();
1839 t1 = t;
1840 }
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001841 }
1842 if (t1 != last && *t1 == '_' && ++t1 != last)
1843 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001844 const char* t = parse_type(t1, last, db);
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001845 if (t != t1)
1846 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001847 if (db.names.empty())
1848 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001849 db.names.back().first += " vector[" + num + "]";
1850 first = t;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001851 }
1852 }
1853 }
1854 }
1855 return first;
1856}
1857
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001858// <type> ::= <builtin-type>
1859// ::= <function-type>
1860// ::= <class-enum-type>
1861// ::= <array-type>
1862// ::= <pointer-to-member-type>
1863// ::= <template-param>
1864// ::= <template-template-param> <template-args>
1865// ::= <decltype>
1866// ::= <substitution>
1867// ::= <CV-qualifiers> <type>
1868// ::= P <type> # pointer-to
1869// ::= R <type> # reference-to
1870// ::= O <type> # rvalue reference-to (C++0x)
1871// ::= C <type> # complex pair (C 2000)
1872// ::= G <type> # imaginary (C 2000)
1873// ::= Dp <type> # pack expansion (C++0x)
1874// ::= U <source-name> <type> # vendor extended type qualifier
Howard Hinnant19e36dd2013-06-19 13:43:18 +00001875// extension := U <objc-name> <objc-type> # objc-type<identifier>
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001876// extension := <vector-type> # <vector-type> starts with Dv
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001877
Howard Hinnant19e36dd2013-06-19 13:43:18 +00001878// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
1879// <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
1880
Howard Hinnant6c33e762013-06-17 18:10:34 +00001881template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001882const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001883parse_type(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001884{
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001885 if (first != last)
1886 {
1887 switch (*first)
1888 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001889 case 'r':
1890 case 'V':
1891 case 'K':
1892 {
1893 unsigned cv = 0;
1894 const char* t = parse_cv_qualifiers(first, last, cv);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001895 if (t != first)
1896 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001897 bool is_function = *t == 'F';
1898 size_t k0 = db.names.size();
1899 const char* t1 = parse_type(t, last, db);
1900 size_t k1 = db.names.size();
1901 if (t1 != t)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001902 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001903 if (is_function)
1904 db.subs.pop_back();
1905 db.subs.emplace_back(db.names.get_allocator());
1906 for (size_t k = k0; k < k1; ++k)
1907 {
1908 if (is_function)
1909 {
1910 size_t p = db.names[k].second.size();
1911 if (db.names[k].second[p-2] == '&')
1912 p -= 3;
1913 else if (db.names[k].second.back() == '&')
1914 p -= 2;
1915 if (cv & 1)
1916 {
1917 db.names[k].second.insert(p, " const");
1918 p += 6;
1919 }
1920 if (cv & 2)
1921 {
1922 db.names[k].second.insert(p, " volatile");
1923 p += 9;
1924 }
1925 if (cv & 4)
1926 db.names[k].second.insert(p, " restrict");
1927 }
1928 else
1929 {
1930 if (cv & 1)
1931 db.names[k].first.append(" const");
1932 if (cv & 2)
1933 db.names[k].first.append(" volatile");
1934 if (cv & 4)
1935 db.names[k].first.append(" restrict");
1936 }
1937 db.subs.back().push_back(db.names[k]);
1938 }
1939 first = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001940 }
1941 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001942 }
1943 break;
1944 default:
1945 {
1946 const char* t = parse_builtin_type(first, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001947 if (t != first)
1948 {
1949 first = t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001950 }
1951 else
1952 {
1953 switch (*first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001954 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001955 case 'A':
1956 t = parse_array_type(first, last, db);
1957 if (t != first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001958 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001959 if (db.names.empty())
1960 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001961 first = t;
1962 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
1963 }
1964 break;
1965 case 'C':
1966 t = parse_type(first+1, last, db);
1967 if (t != first+1)
1968 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001969 if (db.names.empty())
1970 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001971 db.names.back().first.append(" complex");
1972 first = t;
1973 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
1974 }
1975 break;
1976 case 'F':
1977 t = parse_function_type(first, last, db);
1978 if (t != first)
1979 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001980 if (db.names.empty())
1981 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001982 first = t;
1983 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
1984 }
1985 break;
1986 case 'G':
1987 t = parse_type(first+1, last, db);
1988 if (t != first+1)
1989 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001990 if (db.names.empty())
1991 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001992 db.names.back().first.append(" imaginary");
1993 first = t;
1994 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
1995 }
1996 break;
1997 case 'M':
1998 t = parse_pointer_to_member_type(first, last, db);
1999 if (t != first)
2000 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002001 if (db.names.empty())
2002 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002003 first = t;
2004 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2005 }
2006 break;
2007 case 'O':
2008 {
2009 size_t k0 = db.names.size();
2010 t = parse_type(first+1, last, db);
2011 size_t k1 = db.names.size();
2012 if (t != first+1)
2013 {
2014 db.subs.emplace_back(db.names.get_allocator());
2015 for (size_t k = k0; k < k1; ++k)
2016 {
2017 if (db.names[k].second.substr(0, 2) == " [")
2018 {
2019 db.names[k].first += " (";
2020 db.names[k].second.insert(0, ")");
2021 }
2022 else if (db.names[k].second.front() == '(')
2023 {
2024 db.names[k].first += "(";
2025 db.names[k].second.insert(0, ")");
2026 }
2027 db.names[k].first.append("&&");
2028 db.subs.back().push_back(db.names[k]);
2029 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002030 first = t;
2031 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002032 break;
2033 }
2034 case 'P':
2035 {
2036 size_t k0 = db.names.size();
2037 t = parse_type(first+1, last, db);
2038 size_t k1 = db.names.size();
2039 if (t != first+1)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002040 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002041 db.subs.emplace_back(db.names.get_allocator());
2042 for (size_t k = k0; k < k1; ++k)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002043 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002044 if (db.names[k].second.substr(0, 2) == " [")
2045 {
2046 db.names[k].first += " (";
2047 db.names[k].second.insert(0, ")");
2048 }
2049 else if (db.names[k].second.front() == '(')
2050 {
2051 db.names[k].first += "(";
2052 db.names[k].second.insert(0, ")");
2053 }
Howard Hinnant19e36dd2013-06-19 13:43:18 +00002054 if (first[1] != 'U' || db.names[k].first.substr(0, 12) != "objc_object<")
2055 {
2056 db.names[k].first.append("*");
2057 }
2058 else
2059 {
2060 db.names[k].first.replace(0, 11, "id");
2061 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002062 db.subs.back().push_back(db.names[k]);
2063 }
2064 first = t;
2065 }
2066 break;
2067 }
2068 case 'R':
2069 {
2070 size_t k0 = db.names.size();
2071 t = parse_type(first+1, last, db);
2072 size_t k1 = db.names.size();
2073 if (t != first+1)
2074 {
2075 db.subs.emplace_back(db.names.get_allocator());
2076 for (size_t k = k0; k < k1; ++k)
2077 {
2078 if (db.names[k].second.substr(0, 2) == " [")
2079 {
2080 db.names[k].first += " (";
2081 db.names[k].second.insert(0, ")");
2082 }
2083 else if (db.names[k].second.front() == '(')
2084 {
2085 db.names[k].first += "(";
2086 db.names[k].second.insert(0, ")");
2087 }
2088 db.names[k].first.append("&");
2089 db.subs.back().push_back(db.names[k]);
2090 }
2091 first = t;
2092 }
2093 break;
2094 }
2095 case 'T':
2096 {
2097 size_t k0 = db.names.size();
2098 t = parse_template_param(first, last, db);
2099 size_t k1 = db.names.size();
2100 if (t != first)
2101 {
2102 db.subs.emplace_back(db.names.get_allocator());
2103 for (size_t k = k0; k < k1; ++k)
2104 db.subs.back().push_back(db.names[k]);
2105 if (db.try_to_parse_template_args && k1 == k0+1)
2106 {
2107 const char* t1 = parse_template_args(t, last, db);
2108 if (t1 != t)
2109 {
2110 auto args = db.names.back().move_full();
2111 db.names.pop_back();
2112 db.names.back().first += std::move(args);
2113 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2114 t = t1;
2115 }
2116 }
2117 first = t;
2118 }
2119 break;
2120 }
2121 case 'U':
2122 if (first+1 != last)
2123 {
2124 t = parse_source_name(first+1, last, db);
2125 if (t != first+1)
2126 {
2127 const char* t2 = parse_type(t, last, db);
2128 if (t2 != t)
2129 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002130 if (db.names.size() < 2)
2131 return first;
Howard Hinnant19e36dd2013-06-19 13:43:18 +00002132 auto type = db.names.back().move_full();
Howard Hinnant6c33e762013-06-17 18:10:34 +00002133 db.names.pop_back();
Howard Hinnant19e36dd2013-06-19 13:43:18 +00002134 if (db.names.back().first.substr(0, 9) != "objcproto")
2135 {
2136 db.names.back() = type + " " + db.names.back().move_full();
2137 }
2138 else
2139 {
2140 auto proto = db.names.back().move_full();
2141 db.names.pop_back();
2142 t = parse_source_name(proto.data() + 9, proto.data() + proto.size(), db);
2143 if (t != proto.data() + 9)
2144 {
2145 db.names.back() = type + "<" + db.names.back().move_full() + ">";
2146 }
2147 else
2148 {
2149 db.names.push_back(type + " " + proto);
2150 }
2151 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002152 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2153 first = t2;
2154 }
2155 }
2156 }
2157 break;
2158 case 'S':
2159 if (first+1 != last && first[1] == 't')
2160 {
2161 t = parse_name(first, last, db);
2162 if (t != first)
2163 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002164 if (db.names.empty())
2165 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002166 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002167 first = t;
2168 }
2169 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002170 else
2171 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002172 t = parse_substitution(first, last, db);
2173 if (t != first)
2174 {
2175 first = t;
2176 // Parsed a substitution. If the substitution is a
2177 // <template-param> it might be followed by <template-args>.
2178 t = parse_template_args(first, last, db);
2179 if (t != first)
2180 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002181 if (db.names.size() < 2)
2182 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002183 auto template_args = db.names.back().move_full();
2184 db.names.pop_back();
2185 db.names.back().first += template_args;
2186 // Need to create substitution for <template-template-param> <template-args>
2187 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2188 first = t;
2189 }
2190 }
2191 }
2192 break;
2193 case 'D':
2194 if (first+1 != last)
2195 {
2196 switch (first[1])
2197 {
2198 case 'p':
2199 {
2200 size_t k0 = db.names.size();
2201 t = parse_type(first+2, last, db);
2202 size_t k1 = db.names.size();
Howard Hinnantf6725172013-06-21 17:04:24 +00002203 if (t != first+2)
Howard Hinnant6c33e762013-06-17 18:10:34 +00002204 {
2205 db.subs.emplace_back(db.names.get_allocator());
2206 for (size_t k = k0; k < k1; ++k)
2207 db.subs.back().push_back(db.names[k]);
2208 first = t;
2209 return first;
2210 }
2211 break;
2212 }
2213 case 't':
2214 case 'T':
2215 t = parse_decltype(first, last, db);
2216 if (t != first)
2217 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002218 if (db.names.empty())
2219 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002220 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2221 first = t;
2222 return first;
2223 }
2224 break;
2225 case 'v':
2226 t = parse_vector_type(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 }
2237 }
2238 // drop through
2239 default:
2240 // must check for builtin-types before class-enum-types to avoid
2241 // ambiguities with operator-names
2242 t = parse_builtin_type(first, last, db);
2243 if (t != first)
2244 {
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002245 first = t;
2246 }
Howard Hinnantab87dcf2011-12-15 20:02:15 +00002247 else
2248 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002249 t = parse_name(first, last, db);
2250 if (t != first)
2251 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002252 if (db.names.empty())
2253 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002254 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2255 first = t;
2256 }
Howard Hinnantab87dcf2011-12-15 20:02:15 +00002257 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002258 break;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00002259 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002260 }
2261 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002262 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002263 }
2264 }
2265 return first;
2266}
2267
2268// <operator-name>
2269// ::= aa # &&
2270// ::= ad # & (unary)
2271// ::= an # &
2272// ::= aN # &=
2273// ::= aS # =
2274// ::= cl # ()
2275// ::= cm # ,
2276// ::= co # ~
2277// ::= cv <type> # (cast)
2278// ::= da # delete[]
2279// ::= de # * (unary)
2280// ::= dl # delete
2281// ::= dv # /
2282// ::= dV # /=
2283// ::= eo # ^
2284// ::= eO # ^=
2285// ::= eq # ==
2286// ::= ge # >=
2287// ::= gt # >
2288// ::= ix # []
2289// ::= le # <=
Howard Hinnantf29757a2014-01-06 23:05:04 +00002290// ::= li <source-name> # operator ""
Howard Hinnant6c33e762013-06-17 18:10:34 +00002291// ::= ls # <<
2292// ::= lS # <<=
2293// ::= lt # <
2294// ::= mi # -
2295// ::= mI # -=
2296// ::= ml # *
2297// ::= mL # *=
2298// ::= mm # -- (postfix in <expression> context)
2299// ::= na # new[]
2300// ::= ne # !=
2301// ::= ng # - (unary)
2302// ::= nt # !
2303// ::= nw # new
2304// ::= oo # ||
2305// ::= or # |
2306// ::= oR # |=
2307// ::= pm # ->*
2308// ::= pl # +
2309// ::= pL # +=
2310// ::= pp # ++ (postfix in <expression> context)
2311// ::= ps # + (unary)
2312// ::= pt # ->
2313// ::= qu # ?
2314// ::= rm # %
2315// ::= rM # %=
2316// ::= rs # >>
2317// ::= rS # >>=
2318// ::= v <digit> <source-name> # vendor extended operator
2319
2320template <class C>
2321const char*
2322parse_operator_name(const char* first, const char* last, C& db)
2323{
2324 if (last - first >= 2)
2325 {
2326 switch (first[0])
2327 {
2328 case 'a':
2329 switch (first[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002330 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002331 case 'a':
2332 db.names.push_back("operator&&");
2333 first += 2;
2334 break;
2335 case 'd':
2336 case 'n':
2337 db.names.push_back("operator&");
2338 first += 2;
2339 break;
2340 case 'N':
2341 db.names.push_back("operator&=");
2342 first += 2;
2343 break;
2344 case 'S':
2345 db.names.push_back("operator=");
2346 first += 2;
2347 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002348 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002349 break;
2350 case 'c':
2351 switch (first[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002352 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002353 case 'l':
2354 db.names.push_back("operator()");
2355 first += 2;
2356 break;
2357 case 'm':
2358 db.names.push_back("operator,");
2359 first += 2;
2360 break;
2361 case 'o':
2362 db.names.push_back("operator~");
2363 first += 2;
2364 break;
2365 case 'v':
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002366 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002367 bool try_to_parse_template_args = db.try_to_parse_template_args;
2368 db.try_to_parse_template_args = false;
2369 const char* t = parse_type(first+2, last, db);
2370 db.try_to_parse_template_args = try_to_parse_template_args;
2371 if (t != first+2)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002372 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002373 if (db.names.empty())
2374 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002375 db.names.back().first.insert(0, "operator ");
2376 db.parsed_ctor_dtor_cv = true;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002377 first = t;
2378 }
2379 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002380 break;
2381 }
2382 break;
2383 case 'd':
2384 switch (first[1])
2385 {
2386 case 'a':
2387 db.names.push_back("operator delete[]");
2388 first += 2;
2389 break;
2390 case 'e':
2391 db.names.push_back("operator*");
2392 first += 2;
2393 break;
2394 case 'l':
2395 db.names.push_back("operator delete");
2396 first += 2;
2397 break;
2398 case 'v':
2399 db.names.push_back("operator/");
2400 first += 2;
2401 break;
2402 case 'V':
2403 db.names.push_back("operator/=");
2404 first += 2;
2405 break;
2406 }
2407 break;
2408 case 'e':
2409 switch (first[1])
2410 {
2411 case 'o':
2412 db.names.push_back("operator^");
2413 first += 2;
2414 break;
2415 case 'O':
2416 db.names.push_back("operator^=");
2417 first += 2;
2418 break;
2419 case 'q':
2420 db.names.push_back("operator==");
2421 first += 2;
2422 break;
2423 }
2424 break;
2425 case 'g':
2426 switch (first[1])
2427 {
2428 case 'e':
2429 db.names.push_back("operator>=");
2430 first += 2;
2431 break;
2432 case 't':
2433 db.names.push_back("operator>");
2434 first += 2;
2435 break;
2436 }
2437 break;
2438 case 'i':
2439 if (first[1] == 'x')
2440 {
2441 db.names.push_back("operator[]");
2442 first += 2;
2443 }
2444 break;
2445 case 'l':
2446 switch (first[1])
2447 {
2448 case 'e':
2449 db.names.push_back("operator<=");
2450 first += 2;
2451 break;
Howard Hinnantf29757a2014-01-06 23:05:04 +00002452 case 'i':
2453 {
2454 const char* t = parse_source_name(first+2, last, db);
2455 if (t != first+2)
2456 {
2457 if (db.names.empty())
2458 return first;
2459 db.names.back().first.insert(0, "operator\"\" ");
2460 first = t;
2461 }
2462 }
2463 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002464 case 's':
2465 db.names.push_back("operator<<");
2466 first += 2;
2467 break;
2468 case 'S':
2469 db.names.push_back("operator<<=");
2470 first += 2;
2471 break;
2472 case 't':
2473 db.names.push_back("operator<");
2474 first += 2;
2475 break;
2476 }
2477 break;
2478 case 'm':
2479 switch (first[1])
2480 {
2481 case 'i':
2482 db.names.push_back("operator-");
2483 first += 2;
2484 break;
2485 case 'I':
2486 db.names.push_back("operator-=");
2487 first += 2;
2488 break;
2489 case 'l':
2490 db.names.push_back("operator*");
2491 first += 2;
2492 break;
2493 case 'L':
2494 db.names.push_back("operator*=");
2495 first += 2;
2496 break;
2497 case 'm':
2498 db.names.push_back("operator--");
2499 first += 2;
2500 break;
2501 }
2502 break;
2503 case 'n':
2504 switch (first[1])
2505 {
2506 case 'a':
2507 db.names.push_back("operator new[]");
2508 first += 2;
2509 break;
2510 case 'e':
2511 db.names.push_back("operator!=");
2512 first += 2;
2513 break;
2514 case 'g':
2515 db.names.push_back("operator-");
2516 first += 2;
2517 break;
2518 case 't':
2519 db.names.push_back("operator!");
2520 first += 2;
2521 break;
2522 case 'w':
2523 db.names.push_back("operator new");
2524 first += 2;
2525 break;
2526 }
2527 break;
2528 case 'o':
2529 switch (first[1])
2530 {
2531 case 'o':
2532 db.names.push_back("operator||");
2533 first += 2;
2534 break;
2535 case 'r':
2536 db.names.push_back("operator|");
2537 first += 2;
2538 break;
2539 case 'R':
2540 db.names.push_back("operator|=");
2541 first += 2;
2542 break;
2543 }
2544 break;
2545 case 'p':
2546 switch (first[1])
2547 {
2548 case 'm':
2549 db.names.push_back("operator->*");
2550 first += 2;
2551 break;
2552 case 'l':
2553 db.names.push_back("operator+");
2554 first += 2;
2555 break;
2556 case 'L':
2557 db.names.push_back("operator+=");
2558 first += 2;
2559 break;
2560 case 'p':
2561 db.names.push_back("operator++");
2562 first += 2;
2563 break;
2564 case 's':
2565 db.names.push_back("operator+");
2566 first += 2;
2567 break;
2568 case 't':
2569 db.names.push_back("operator->");
2570 first += 2;
2571 break;
2572 }
2573 break;
2574 case 'q':
2575 if (first[1] == 'u')
2576 {
2577 db.names.push_back("operator?");
2578 first += 2;
2579 }
2580 break;
2581 case 'r':
2582 switch (first[1])
2583 {
2584 case 'm':
2585 db.names.push_back("operator%");
2586 first += 2;
2587 break;
2588 case 'M':
2589 db.names.push_back("operator%=");
2590 first += 2;
2591 break;
2592 case 's':
2593 db.names.push_back("operator>>");
2594 first += 2;
2595 break;
2596 case 'S':
2597 db.names.push_back("operator>>=");
2598 first += 2;
2599 break;
2600 }
2601 break;
2602 case 'v':
2603 if (std::isdigit(first[1]))
2604 {
2605 const char* t = parse_source_name(first+2, last, db);
2606 if (t != first+2)
2607 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002608 if (db.names.empty())
2609 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002610 db.names.back().first.insert(0, "operator ");
2611 first = t;
2612 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002613 }
2614 break;
2615 }
2616 }
2617 return first;
2618}
2619
Howard Hinnant6c33e762013-06-17 18:10:34 +00002620template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002621const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00002622parse_integer_literal(const char* first, const char* last, const typename C::String& lit, C& db)
2623{
2624 const char* t = parse_number(first, last);
2625 if (t != first && t != last && *t == 'E')
2626 {
2627 if (lit.size() > 3)
2628 db.names.push_back("(" + lit + ")");
2629 else
2630 db.names.emplace_back();
2631 if (*first == 'n')
2632 {
2633 db.names.back().first += '-';
2634 ++first;
2635 }
2636 db.names.back().first.append(first, t);
2637 if (lit.size() <= 3)
2638 db.names.back().first += lit;
2639 first = t+1;
2640 }
2641 return first;
2642}
2643
2644// <expr-primary> ::= L <type> <value number> E # integer literal
2645// ::= L <type> <value float> E # floating literal
2646// ::= L <string type> E # string literal
2647// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
2648// ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
2649// ::= L <mangled-name> E # external name
2650
2651template <class C>
2652const char*
2653parse_expr_primary(const char* first, const char* last, C& db)
2654{
2655 if (last - first >= 4 && *first == 'L')
2656 {
2657 switch (first[1])
2658 {
2659 case 'w':
Howard Hinnant93433df2013-06-20 21:49:34 +00002660 {
2661 const char* t = parse_integer_literal(first+2, last, "wchar_t", db);
2662 if (t != first+2)
2663 first = t;
2664 }
2665 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002666 case 'b':
2667 if (first[3] == 'E')
2668 {
2669 switch (first[2])
2670 {
2671 case '0':
2672 db.names.push_back("false");
2673 first += 4;
2674 break;
2675 case '1':
2676 db.names.push_back("true");
2677 first += 4;
2678 break;
2679 }
2680 }
2681 break;
2682 case 'c':
Howard Hinnant93433df2013-06-20 21:49:34 +00002683 {
2684 const char* t = parse_integer_literal(first+2, last, "char", db);
2685 if (t != first+2)
2686 first = t;
2687 }
2688 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002689 case 'a':
Howard Hinnant93433df2013-06-20 21:49:34 +00002690 {
2691 const char* t = parse_integer_literal(first+2, last, "signed char", db);
2692 if (t != first+2)
2693 first = t;
2694 }
2695 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002696 case 'h':
Howard Hinnant93433df2013-06-20 21:49:34 +00002697 {
2698 const char* t = parse_integer_literal(first+2, last, "unsigned char", db);
2699 if (t != first+2)
2700 first = t;
2701 }
2702 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002703 case 's':
Howard Hinnant93433df2013-06-20 21:49:34 +00002704 {
2705 const char* t = parse_integer_literal(first+2, last, "short", db);
2706 if (t != first+2)
2707 first = t;
2708 }
2709 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002710 case 't':
Howard Hinnant93433df2013-06-20 21:49:34 +00002711 {
2712 const char* t = parse_integer_literal(first+2, last, "unsigned short", db);
2713 if (t != first+2)
2714 first = t;
2715 }
2716 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002717 case 'i':
Howard Hinnant93433df2013-06-20 21:49:34 +00002718 {
2719 const char* t = parse_integer_literal(first+2, last, "", db);
2720 if (t != first+2)
2721 first = t;
2722 }
2723 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002724 case 'j':
Howard Hinnant93433df2013-06-20 21:49:34 +00002725 {
2726 const char* t = parse_integer_literal(first+2, last, "u", db);
2727 if (t != first+2)
2728 first = t;
2729 }
2730 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002731 case 'l':
Howard Hinnant93433df2013-06-20 21:49:34 +00002732 {
2733 const char* t = parse_integer_literal(first+2, last, "l", db);
2734 if (t != first+2)
2735 first = t;
2736 }
2737 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002738 case 'm':
Howard Hinnant93433df2013-06-20 21:49:34 +00002739 {
2740 const char* t = parse_integer_literal(first+2, last, "ul", db);
2741 if (t != first+2)
2742 first = t;
2743 }
2744 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002745 case 'x':
Howard Hinnant93433df2013-06-20 21:49:34 +00002746 {
2747 const char* t = parse_integer_literal(first+2, last, "ll", db);
2748 if (t != first+2)
2749 first = t;
2750 }
2751 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002752 case 'y':
Howard Hinnant93433df2013-06-20 21:49:34 +00002753 {
2754 const char* t = parse_integer_literal(first+2, last, "ull", db);
2755 if (t != first+2)
2756 first = t;
2757 }
2758 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002759 case 'n':
Howard Hinnant93433df2013-06-20 21:49:34 +00002760 {
2761 const char* t = parse_integer_literal(first+2, last, "__int128", db);
2762 if (t != first+2)
2763 first = t;
2764 }
2765 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002766 case 'o':
Howard Hinnant93433df2013-06-20 21:49:34 +00002767 {
2768 const char* t = parse_integer_literal(first+2, last, "unsigned __int128", db);
2769 if (t != first+2)
2770 first = t;
2771 }
2772 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002773 case 'f':
Howard Hinnant93433df2013-06-20 21:49:34 +00002774 {
2775 const char* t = parse_floating_number<float>(first+2, last, db);
2776 if (t != first+2)
2777 first = t;
2778 }
2779 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002780 case 'd':
Howard Hinnant93433df2013-06-20 21:49:34 +00002781 {
2782 const char* t = parse_floating_number<double>(first+2, last, db);
2783 if (t != first+2)
2784 first = t;
2785 }
2786 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002787 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00002788 {
2789 const char* t = parse_floating_number<long double>(first+2, last, db);
2790 if (t != first+2)
2791 first = t;
2792 }
2793 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002794 case '_':
2795 if (first[2] == 'Z')
2796 {
2797 const char* t = parse_encoding(first+3, last, db);
2798 if (t != first+3 && t != last && *t == 'E')
2799 first = t+1;
2800 }
2801 break;
2802 case 'T':
2803 // Invalid mangled name per
2804 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
2805 break;
2806 default:
2807 {
2808 // might be named type
2809 const char* t = parse_type(first+1, last, db);
2810 if (t != first+1 && t != last)
2811 {
2812 if (*t != 'E')
2813 {
2814 const char* n = t;
2815 for (; n != last && isdigit(*n); ++n)
2816 ;
2817 if (n != t && n != last && *n == 'E')
2818 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002819 if (db.names.empty())
2820 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002821 db.names.back() = "(" + db.names.back().move_full() + ")" + typename C::String(t, n);
2822 first = n+1;
2823 break;
2824 }
2825 }
2826 else
2827 {
2828 first = t+1;
2829 break;
2830 }
2831 }
2832 }
2833 }
2834 }
2835 return first;
2836}
2837
2838template <class String>
2839String
2840base_name(String& s)
2841{
2842 if (s.empty())
2843 return s;
2844 if (s == "std::string")
2845 {
2846 s = "std::basic_string<char, std::char_traits<char>, std::allocator<char> >";
2847 return "basic_string";
2848 }
2849 if (s == "std::istream")
2850 {
2851 s = "std::basic_istream<char, std::char_traits<char> >";
2852 return "basic_istream";
2853 }
2854 if (s == "std::ostream")
2855 {
2856 s = "std::basic_ostream<char, std::char_traits<char> >";
2857 return "basic_ostream";
2858 }
2859 if (s == "std::iostream")
2860 {
2861 s = "std::basic_iostream<char, std::char_traits<char> >";
2862 return "basic_iostream";
2863 }
2864 const char* const pf = s.data();
2865 const char* pe = pf + s.size();
2866 if (pe[-1] == '>')
2867 {
2868 unsigned c = 1;
2869 while (true)
2870 {
2871 if (--pe == pf)
2872 return String();
2873 if (pe[-1] == '<')
2874 {
2875 if (--c == 0)
2876 {
2877 --pe;
2878 break;
2879 }
2880 }
2881 else if (pe[-1] == '>')
2882 ++c;
2883 }
2884 }
2885 const char* p0 = pe - 1;
2886 for (; p0 != pf; --p0)
2887 {
2888 if (*p0 == ':')
2889 {
2890 ++p0;
2891 break;
2892 }
2893 }
2894 return String(p0, pe);
2895}
2896
2897// <ctor-dtor-name> ::= C1 # complete object constructor
2898// ::= C2 # base object constructor
2899// ::= C3 # complete object allocating constructor
2900// extension ::= C5 # ?
2901// ::= D0 # deleting destructor
2902// ::= D1 # complete object destructor
2903// ::= D2 # base object destructor
2904// extension ::= D5 # ?
2905
2906template <class C>
2907const char*
2908parse_ctor_dtor_name(const char* first, const char* last, C& db)
2909{
2910 if (last-first >= 2 && !db.names.empty())
2911 {
2912 switch (first[0])
2913 {
2914 case 'C':
2915 switch (first[1])
2916 {
2917 case '1':
2918 case '2':
2919 case '3':
2920 case '5':
Howard Hinnant753a30d2013-12-11 19:44:25 +00002921 if (db.names.empty())
2922 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002923 db.names.push_back(base_name(db.names.back().first));
2924 first += 2;
2925 db.parsed_ctor_dtor_cv = true;
2926 break;
2927 }
2928 break;
2929 case 'D':
2930 switch (first[1])
2931 {
2932 case '0':
2933 case '1':
2934 case '2':
2935 case '5':
Howard Hinnant753a30d2013-12-11 19:44:25 +00002936 if (db.names.empty())
2937 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002938 db.names.push_back("~" + base_name(db.names.back().first));
2939 first += 2;
2940 db.parsed_ctor_dtor_cv = true;
2941 break;
2942 }
2943 break;
2944 }
2945 }
2946 return first;
2947}
2948
2949// <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
2950// ::= <closure-type-name>
2951//
2952// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2953//
2954// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
2955
2956template <class C>
2957const char*
2958parse_unnamed_type_name(const char* first, const char* last, C& db)
2959{
2960 if (last - first > 2 && first[0] == 'U')
2961 {
2962 char type = first[1];
2963 switch (type)
2964 {
2965 case 't':
2966 {
2967 db.names.push_back(typename C::String("'unnamed"));
2968 const char* t0 = first+2;
2969 if (t0 == last)
2970 {
2971 db.names.pop_back();
2972 return first;
2973 }
2974 if (std::isdigit(*t0))
2975 {
2976 const char* t1 = t0 + 1;
2977 while (t1 != last && std::isdigit(*t1))
2978 ++t1;
2979 db.names.back().first.append(t0, t1);
2980 t0 = t1;
2981 }
2982 db.names.back().first.push_back('\'');
2983 if (t0 == last || *t0 != '_')
2984 {
2985 db.names.pop_back();
2986 return first;
2987 }
2988 first = t0 + 1;
2989 }
2990 break;
2991 case 'l':
2992 {
2993 db.names.push_back(typename C::String("'lambda'("));
2994 const char* t0 = first+2;
2995 if (first[2] == 'v')
2996 {
2997 db.names.back().first += ')';
2998 ++t0;
2999 }
3000 else
3001 {
3002 const char* t1 = parse_type(t0, last, db);
3003 if (t1 == t0)
3004 {
3005 db.names.pop_back();
3006 return first;
3007 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00003008 if (db.names.size() < 2)
3009 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003010 auto tmp = db.names.back().move_full();
3011 db.names.pop_back();
3012 db.names.back().first.append(tmp);
3013 t0 = t1;
3014 while (true)
3015 {
3016 t1 = parse_type(t0, last, db);
3017 if (t1 == t0)
3018 break;
Howard Hinnant753a30d2013-12-11 19:44:25 +00003019 if (db.names.size() < 2)
3020 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003021 tmp = db.names.back().move_full();
3022 db.names.pop_back();
3023 if (!tmp.empty())
3024 {
3025 db.names.back().first.append(", ");
3026 db.names.back().first.append(tmp);
3027 }
3028 t0 = t1;
3029 }
3030 db.names.back().first.append(")");
3031 }
3032 if (t0 == last || *t0 != 'E')
3033 {
3034 db.names.pop_back();
3035 return first;
3036 }
3037 ++t0;
3038 if (t0 == last)
3039 {
3040 db.names.pop_back();
3041 return first;
3042 }
3043 if (std::isdigit(*t0))
3044 {
3045 const char* t1 = t0 + 1;
3046 while (t1 != last && std::isdigit(*t1))
3047 ++t1;
3048 db.names.back().first.insert(db.names.back().first.begin()+7, t0, t1);
3049 t0 = t1;
3050 }
3051 if (t0 == last || *t0 != '_')
3052 {
3053 db.names.pop_back();
3054 return first;
3055 }
3056 first = t0 + 1;
3057 }
3058 break;
3059 }
3060 }
3061 return first;
3062}
3063
3064// <unqualified-name> ::= <operator-name>
3065// ::= <ctor-dtor-name>
3066// ::= <source-name>
3067// ::= <unnamed-type-name>
3068
3069template <class C>
3070const char*
3071parse_unqualified_name(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003072{
3073 if (first != last)
3074 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00003075 const char* t;
3076 switch (*first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003077 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00003078 case 'C':
3079 case 'D':
3080 t = parse_ctor_dtor_name(first, last, db);
3081 if (t != first)
3082 first = t;
3083 break;
3084 case 'U':
3085 t = parse_unnamed_type_name(first, last, db);
3086 if (t != first)
3087 first = t;
3088 break;
3089 case '1':
3090 case '2':
3091 case '3':
3092 case '4':
3093 case '5':
3094 case '6':
3095 case '7':
3096 case '8':
3097 case '9':
3098 t = parse_source_name(first, last, db);
3099 if (t != first)
3100 first = t;
3101 break;
3102 default:
3103 t = parse_operator_name(first, last, db);
3104 if (t != first)
3105 first = t;
3106 break;
3107 };
3108 }
3109 return first;
3110}
3111
3112// <unscoped-name> ::= <unqualified-name>
3113// ::= St <unqualified-name> # ::std::
3114// extension ::= StL<unqualified-name>
3115
3116template <class C>
3117const char*
3118parse_unscoped_name(const char* first, const char* last, C& db)
3119{
3120 if (last - first >= 2)
3121 {
3122 const char* t0 = first;
3123 bool St = false;
3124 if (first[0] == 'S' && first[1] == 't')
3125 {
3126 t0 += 2;
3127 St = true;
3128 if (t0 != last && *t0 == 'L')
3129 ++t0;
3130 }
3131 const char* t1 = parse_unqualified_name(t0, last, db);
3132 if (t1 != t0)
3133 {
3134 if (St)
Howard Hinnant753a30d2013-12-11 19:44:25 +00003135 {
3136 if (db.names.empty())
3137 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003138 db.names.back().first.insert(0, "std::");
Howard Hinnant753a30d2013-12-11 19:44:25 +00003139 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003140 first = t1;
3141 }
3142 }
3143 return first;
3144}
3145
3146// at <type> # alignof (a type)
3147
3148template <class C>
3149const char*
3150parse_alignof_type(const char* first, const char* last, C& db)
3151{
3152 if (last - first >= 3 && first[0] == 'a' && first[1] == 't')
3153 {
3154 const char* t = parse_type(first+2, last, db);
3155 if (t != first+2)
3156 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003157 if (db.names.empty())
3158 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003159 db.names.back().first = "alignof (" + db.names.back().move_full() + ")";
3160 first = t;
3161 }
3162 }
3163 return first;
3164}
3165
3166// az <expression> # alignof (a expression)
3167
3168template <class C>
3169const char*
3170parse_alignof_expr(const char* first, const char* last, C& db)
3171{
3172 if (last - first >= 3 && first[0] == 'a' && first[1] == 'z')
3173 {
3174 const char* t = parse_expression(first+2, last, db);
3175 if (t != first+2)
3176 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003177 if (db.names.empty())
3178 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003179 db.names.back().first = "alignof (" + db.names.back().move_full() + ")";
3180 first = t;
3181 }
3182 }
3183 return first;
3184}
3185
3186template <class C>
3187const char*
3188parse_noexcept_expression(const char* first, const char* last, C& db)
3189{
3190 const char* t1 = parse_expression(first, last, db);
3191 if (t1 != first)
3192 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003193 if (db.names.empty())
3194 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003195 db.names.back().first = "noexcept (" + db.names.back().move_full() + ")";
3196 first = t1;
3197 }
3198 return first;
3199}
3200
3201template <class C>
3202const char*
3203parse_prefix_expression(const char* first, const char* last, const typename C::String& op, C& db)
3204{
3205 const char* t1 = parse_expression(first, last, db);
3206 if (t1 != first)
3207 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003208 if (db.names.empty())
3209 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003210 db.names.back().first = op + "(" + db.names.back().move_full() + ")";
3211 first = t1;
3212 }
3213 return first;
3214}
3215
3216template <class C>
3217const char*
3218parse_binary_expression(const char* first, const char* last, const typename C::String& op, C& db)
3219{
3220 const char* t1 = parse_expression(first, last, db);
3221 if (t1 != first)
3222 {
3223 const char* t2 = parse_expression(t1, last, db);
3224 if (t2 != t1)
3225 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003226 if (db.names.size() < 2)
3227 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003228 auto op2 = db.names.back().move_full();
3229 db.names.pop_back();
3230 auto op1 = db.names.back().move_full();
3231 auto& nm = db.names.back().first;
3232 nm.clear();
3233 if (op == ">")
3234 nm += '(';
3235 nm += "(" + op1 + ") " + op + " (" + op2 + ")";
3236 if (op == ">")
3237 nm += ')';
3238 first = t2;
3239 }
3240 else
3241 db.names.pop_back();
3242 }
3243 return first;
3244}
3245
3246// <expression> ::= <unary operator-name> <expression>
3247// ::= <binary operator-name> <expression> <expression>
3248// ::= <ternary operator-name> <expression> <expression> <expression>
3249// ::= cl <expression>+ E # call
3250// ::= cv <type> <expression> # conversion with one argument
3251// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
3252// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
3253// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
3254// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
3255// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
3256// ::= [gs] dl <expression> # delete expression
3257// ::= [gs] da <expression> # delete[] expression
3258// ::= pp_ <expression> # prefix ++
3259// ::= mm_ <expression> # prefix --
3260// ::= ti <type> # typeid (type)
3261// ::= te <expression> # typeid (expression)
3262// ::= dc <type> <expression> # dynamic_cast<type> (expression)
3263// ::= sc <type> <expression> # static_cast<type> (expression)
3264// ::= cc <type> <expression> # const_cast<type> (expression)
3265// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
3266// ::= st <type> # sizeof (a type)
3267// ::= sz <expression> # sizeof (an expression)
3268// ::= at <type> # alignof (a type)
3269// ::= az <expression> # alignof (an expression)
3270// ::= nx <expression> # noexcept (expression)
3271// ::= <template-param>
3272// ::= <function-param>
3273// ::= dt <expression> <unresolved-name> # expr.name
3274// ::= pt <expression> <unresolved-name> # expr->name
3275// ::= ds <expression> <expression> # expr.*expr
3276// ::= sZ <template-param> # size of a parameter pack
3277// ::= sZ <function-param> # size of a function parameter pack
3278// ::= sp <expression> # pack expansion
3279// ::= tw <expression> # throw expression
3280// ::= tr # throw with no operand (rethrow)
3281// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
3282// # freestanding dependent name (e.g., T::x),
3283// # objectless nonstatic member reference
3284// ::= <expr-primary>
3285
3286template <class C>
3287const char*
3288parse_expression(const char* first, const char* last, C& db)
3289{
3290 if (last - first >= 2)
3291 {
3292 const char* t = first;
3293 bool parsed_gs = false;
3294 if (last - first >= 4 && t[0] == 'g' && t[1] == 's')
3295 {
3296 t += 2;
3297 parsed_gs = true;
3298 }
3299 switch (*t)
3300 {
3301 case 'L':
3302 first = parse_expr_primary(first, last, db);
3303 break;
3304 case 'T':
3305 first = parse_template_param(first, last, db);
3306 break;
3307 case 'f':
3308 first = parse_function_param(first, last, db);
3309 break;
3310 case 'a':
3311 switch (t[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003312 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00003313 case 'a':
Howard Hinnant93433df2013-06-20 21:49:34 +00003314 t = parse_binary_expression(first+2, last, "&&", db);
3315 if (t != first+2)
3316 first = t;
3317 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003318 case 'd':
Howard Hinnant93433df2013-06-20 21:49:34 +00003319 t = parse_prefix_expression(first+2, last, "&", db);
3320 if (t != first+2)
3321 first = t;
3322 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003323 case 'n':
Howard Hinnant93433df2013-06-20 21:49:34 +00003324 t = parse_binary_expression(first+2, last, "&", db);
3325 if (t != first+2)
3326 first = t;
3327 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003328 case 'N':
Howard Hinnant93433df2013-06-20 21:49:34 +00003329 t = parse_binary_expression(first+2, last, "&=", db);
3330 if (t != first+2)
3331 first = t;
3332 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003333 case 'S':
Howard Hinnant93433df2013-06-20 21:49:34 +00003334 t = parse_binary_expression(first+2, last, "=", db);
3335 if (t != first+2)
3336 first = t;
3337 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003338 case 't':
3339 first = parse_alignof_type(first, last, db);
3340 break;
3341 case 'z':
3342 first = parse_alignof_expr(first, last, db);
3343 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003344 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003345 break;
3346 case 'c':
3347 switch (t[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003348 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00003349 case 'c':
3350 first = parse_const_cast_expr(first, last, db);
3351 break;
3352 case 'l':
3353 first = parse_call_expr(first, last, db);
3354 break;
3355 case 'm':
Howard Hinnant93433df2013-06-20 21:49:34 +00003356 t = parse_binary_expression(first+2, last, ",", db);
3357 if (t != first+2)
3358 first = t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003359 break;
3360 case 'o':
Howard Hinnant93433df2013-06-20 21:49:34 +00003361 t = parse_prefix_expression(first+2, last, "~", db);
3362 if (t != first+2)
3363 first = t;
3364 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003365 case 'v':
3366 first = parse_conversion_expr(first, last, db);
3367 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003368 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003369 break;
3370 case 'd':
3371 switch (t[1])
3372 {
3373 case 'a':
3374 {
3375 const char* t1 = parse_expression(t+2, last, db);
3376 if (t1 != t+2)
3377 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003378 if (db.names.empty())
3379 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003380 db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) +
3381 "delete[] " + db.names.back().move_full();
3382 first = t1;
3383 }
3384 }
3385 break;
3386 case 'c':
3387 first = parse_dynamic_cast_expr(first, last, db);
3388 break;
3389 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00003390 t = parse_prefix_expression(first+2, last, "*", db);
3391 if (t != first+2)
3392 first = t;
3393 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003394 case 'l':
3395 {
3396 const char* t1 = parse_expression(t+2, last, db);
3397 if (t1 != t+2)
3398 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003399 if (db.names.empty())
3400 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003401 db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) +
3402 "delete " + db.names.back().move_full();
3403 first = t1;
3404 }
3405 }
3406 break;
3407 case 'n':
3408 return parse_unresolved_name(first, last, db);
3409 case 's':
3410 first = parse_dot_star_expr(first, last, db);
3411 break;
3412 case 't':
3413 first = parse_dot_expr(first, last, db);
3414 break;
3415 case 'v':
Howard Hinnant93433df2013-06-20 21:49:34 +00003416 t = parse_binary_expression(first+2, last, "/", db);
3417 if (t != first+2)
3418 first = t;
3419 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003420 case 'V':
Howard Hinnant93433df2013-06-20 21:49:34 +00003421 t = parse_binary_expression(first+2, last, "/=", db);
3422 if (t != first+2)
3423 first = t;
3424 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003425 }
3426 break;
3427 case 'e':
3428 switch (t[1])
3429 {
3430 case 'o':
Howard Hinnant93433df2013-06-20 21:49:34 +00003431 t = parse_binary_expression(first+2, last, "^", db);
3432 if (t != first+2)
3433 first = t;
3434 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003435 case 'O':
Howard Hinnant93433df2013-06-20 21:49:34 +00003436 t = parse_binary_expression(first+2, last, "^=", db);
3437 if (t != first+2)
3438 first = t;
3439 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003440 case 'q':
Howard Hinnant93433df2013-06-20 21:49:34 +00003441 t = parse_binary_expression(first+2, last, "==", db);
3442 if (t != first+2)
3443 first = t;
3444 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003445 }
3446 break;
3447 case 'g':
3448 switch (t[1])
3449 {
3450 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00003451 t = parse_binary_expression(first+2, last, ">=", db);
3452 if (t != first+2)
3453 first = t;
3454 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003455 case 't':
Howard Hinnant93433df2013-06-20 21:49:34 +00003456 t = parse_binary_expression(first+2, last, ">", db);
3457 if (t != first+2)
3458 first = t;
3459 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003460 }
3461 break;
3462 case 'i':
3463 if (t[1] == 'x')
3464 {
3465 const char* t1 = parse_expression(first+2, last, db);
3466 if (t1 != first+2)
3467 {
3468 const char* t2 = parse_expression(t1, last, db);
3469 if (t2 != t1)
3470 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003471 if (db.names.size() < 2)
3472 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003473 auto op2 = db.names.back().move_full();
3474 db.names.pop_back();
3475 auto op1 = db.names.back().move_full();
3476 db.names.back() = "(" + op1 + ")[" + op2 + "]";
3477 first = t2;
3478 }
3479 else
3480 db.names.pop_back();
3481 }
3482 }
3483 break;
3484 case 'l':
3485 switch (t[1])
3486 {
3487 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00003488 t = parse_binary_expression(first+2, last, "<=", db);
3489 if (t != first+2)
3490 first = t;
3491 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003492 case 's':
Howard Hinnant93433df2013-06-20 21:49:34 +00003493 t = parse_binary_expression(first+2, last, "<<", db);
3494 if (t != first+2)
3495 first = t;
3496 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003497 case 'S':
Howard Hinnant93433df2013-06-20 21:49:34 +00003498 t = parse_binary_expression(first+2, last, "<<=", db);
3499 if (t != first+2)
3500 first = t;
3501 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003502 case 't':
Howard Hinnant93433df2013-06-20 21:49:34 +00003503 t = parse_binary_expression(first+2, last, "<", db);
3504 if (t != first+2)
3505 first = t;
3506 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003507 }
3508 break;
3509 case 'm':
3510 switch (t[1])
3511 {
3512 case 'i':
Howard Hinnant93433df2013-06-20 21:49:34 +00003513 t = parse_binary_expression(first+2, last, "-", db);
3514 if (t != first+2)
3515 first = t;
3516 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003517 case 'I':
Howard Hinnant93433df2013-06-20 21:49:34 +00003518 t = parse_binary_expression(first+2, last, "-=", db);
3519 if (t != first+2)
3520 first = t;
3521 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003522 case 'l':
Howard Hinnant93433df2013-06-20 21:49:34 +00003523 t = parse_binary_expression(first+2, last, "*", db);
3524 if (t != first+2)
3525 first = t;
3526 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003527 case 'L':
Howard Hinnant93433df2013-06-20 21:49:34 +00003528 t = parse_binary_expression(first+2, last, "*=", db);
3529 if (t != first+2)
3530 first = t;
3531 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003532 case 'm':
3533 if (first+2 != last && first[2] == '_')
Howard Hinnant93433df2013-06-20 21:49:34 +00003534 {
3535 t = parse_prefix_expression(first+3, last, "--", db);
3536 if (t != first+3)
3537 first = t;
3538 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003539 else
3540 {
3541 const char* t1 = parse_expression(first+2, last, db);
3542 if (t1 != first+2)
3543 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003544 if (db.names.empty())
3545 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003546 db.names.back() = "(" + db.names.back().move_full() + ")--";
3547 first = t1;
3548 }
3549 }
3550 break;
3551 }
3552 break;
3553 case 'n':
3554 switch (t[1])
3555 {
3556 case 'a':
3557 case 'w':
3558 first = parse_new_expr(first, last, db);
3559 break;
3560 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00003561 t = parse_binary_expression(first+2, last, "!=", db);
3562 if (t != first+2)
3563 first = t;
3564 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003565 case 'g':
Howard Hinnant93433df2013-06-20 21:49:34 +00003566 t = parse_prefix_expression(first+2, last, "-", db);
3567 if (t != first+2)
3568 first = t;
3569 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003570 case 't':
Howard Hinnant93433df2013-06-20 21:49:34 +00003571 t = parse_prefix_expression(first+2, last, "!", db);
3572 if (t != first+2)
3573 first = t;
3574 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003575 case 'x':
Howard Hinnant93433df2013-06-20 21:49:34 +00003576 t = parse_noexcept_expression(first+2, last, db);
3577 if (t != first+2)
3578 first = t;
3579 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003580 }
3581 break;
3582 case 'o':
3583 switch (t[1])
3584 {
3585 case 'n':
3586 return parse_unresolved_name(first, last, db);
3587 case 'o':
Howard Hinnant93433df2013-06-20 21:49:34 +00003588 t = parse_binary_expression(first+2, last, "||", db);
3589 if (t != first+2)
3590 first = t;
3591 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003592 case 'r':
Howard Hinnant93433df2013-06-20 21:49:34 +00003593 t = parse_binary_expression(first+2, last, "|", db);
3594 if (t != first+2)
3595 first = t;
3596 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003597 case 'R':
Howard Hinnant93433df2013-06-20 21:49:34 +00003598 t = parse_binary_expression(first+2, last, "|=", db);
3599 if (t != first+2)
3600 first = t;
3601 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003602 }
3603 break;
3604 case 'p':
3605 switch (t[1])
3606 {
3607 case 'm':
Howard Hinnant93433df2013-06-20 21:49:34 +00003608 t = parse_binary_expression(first+2, last, "->*", db);
3609 if (t != first+2)
3610 first = t;
3611 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003612 case 'l':
Howard Hinnant93433df2013-06-20 21:49:34 +00003613 t = parse_binary_expression(first+2, last, "+", db);
3614 if (t != first+2)
3615 first = t;
3616 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003617 case 'L':
Howard Hinnant93433df2013-06-20 21:49:34 +00003618 t = parse_binary_expression(first+2, last, "+=", db);
3619 if (t != first+2)
3620 first = t;
3621 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003622 case 'p':
3623 if (first+2 != last && first[2] == '_')
Howard Hinnant93433df2013-06-20 21:49:34 +00003624 {
3625 t = parse_prefix_expression(first+3, last, "++", db);
3626 if (t != first+3)
3627 first = t;
3628 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003629 else
3630 {
3631 const char* t1 = parse_expression(first+2, last, db);
3632 if (t1 != first+2)
3633 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003634 if (db.names.empty())
3635 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003636 db.names.back() = "(" + db.names.back().move_full() + ")++";
3637 first = t1;
3638 }
3639 }
3640 break;
3641 case 's':
Howard Hinnant93433df2013-06-20 21:49:34 +00003642 t = parse_prefix_expression(first+2, last, "+", db);
3643 if (t != first+2)
3644 first = t;
3645 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003646 case 't':
3647 first = parse_arrow_expr(first, last, db);
3648 break;
3649 }
3650 break;
3651 case 'q':
3652 if (t[1] == 'u')
3653 {
3654 const char* t1 = parse_expression(first+2, last, db);
3655 if (t1 != first+2)
3656 {
3657 const char* t2 = parse_expression(t1, last, db);
3658 if (t2 != t1)
3659 {
3660 const char* t3 = parse_expression(t2, last, db);
3661 if (t3 != t2)
3662 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003663 if (db.names.size() < 3)
3664 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003665 auto op3 = db.names.back().move_full();
3666 db.names.pop_back();
3667 auto op2 = db.names.back().move_full();
3668 db.names.pop_back();
3669 auto op1 = db.names.back().move_full();
3670 db.names.back() = "(" + op1 + ") ? (" + op2 + ") : (" + op3 + ")";
3671 first = t3;
3672 }
3673 else
3674 {
3675 db.names.pop_back();
3676 db.names.pop_back();
3677 }
3678 }
3679 else
3680 db.names.pop_back();
3681 }
3682 }
3683 break;
3684 case 'r':
3685 switch (t[1])
3686 {
3687 case 'c':
3688 first = parse_reinterpret_cast_expr(first, last, db);
3689 break;
3690 case 'm':
Howard Hinnant93433df2013-06-20 21:49:34 +00003691 t = parse_binary_expression(first+2, last, "%", db);
3692 if (t != first+2)
3693 first = t;
3694 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003695 case 'M':
Howard Hinnant93433df2013-06-20 21:49:34 +00003696 t = parse_binary_expression(first+2, last, "%=", db);
3697 if (t != first+2)
3698 first = t;
3699 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003700 case 's':
Howard Hinnant93433df2013-06-20 21:49:34 +00003701 t = parse_binary_expression(first+2, last, ">>", db);
3702 if (t != first+2)
3703 first = t;
3704 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003705 case 'S':
Howard Hinnant93433df2013-06-20 21:49:34 +00003706 t = parse_binary_expression(first+2, last, ">>=", db);
3707 if (t != first+2)
3708 first = t;
3709 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003710 }
3711 break;
3712 case 's':
3713 switch (t[1])
3714 {
3715 case 'c':
3716 first = parse_static_cast_expr(first, last, db);
3717 break;
3718 case 'p':
3719 first = parse_pack_expansion(first, last, db);
3720 break;
3721 case 'r':
3722 return parse_unresolved_name(first, last, db);
3723 case 't':
3724 first = parse_sizeof_type_expr(first, last, db);
3725 break;
3726 case 'z':
3727 first = parse_sizeof_expr_expr(first, last, db);
3728 break;
3729 case 'Z':
3730 if (last - t >= 3)
3731 {
3732 switch (t[2])
3733 {
3734 case 'T':
3735 first = parse_sizeof_param_pack_expr(first, last, db);
3736 break;
3737 case 'f':
3738 first = parse_sizeof_function_param_pack_expr(first, last, db);
3739 break;
3740 }
3741 }
3742 break;
3743 }
3744 break;
3745 case 't':
3746 switch (t[1])
3747 {
3748 case 'e':
3749 case 'i':
3750 first = parse_typeid_expr(first, last, db);
3751 break;
3752 case 'r':
3753 db.names.push_back("throw");
3754 first += 2;
3755 break;
3756 case 'w':
3757 first = parse_throw_expr(first, last, db);
3758 break;
3759 }
3760 break;
3761 case '1':
3762 case '2':
3763 case '3':
3764 case '4':
3765 case '5':
3766 case '6':
3767 case '7':
3768 case '8':
3769 case '9':
3770 return parse_unresolved_name(first, last, db);
3771 }
3772 }
3773 return first;
3774}
3775
3776// <template-arg> ::= <type> # type or template
3777// ::= X <expression> E # expression
3778// ::= <expr-primary> # simple expressions
3779// ::= J <template-arg>* E # argument pack
3780// ::= LZ <encoding> E # extension
3781
3782template <class C>
3783const char*
3784parse_template_arg(const char* first, const char* last, C& db)
3785{
3786 if (first != last)
3787 {
3788 const char* t;
3789 switch (*first)
3790 {
3791 case 'X':
3792 t = parse_expression(first+1, last, db);
3793 if (t != first+1)
3794 {
3795 if (t != last && *t == 'E')
3796 first = t+1;
3797 }
3798 break;
3799 case 'J':
3800 t = first+1;
3801 if (t == last)
3802 return first;
3803 while (*t != 'E')
3804 {
3805 const char* t1 = parse_template_arg(t, last, db);
3806 if (t1 == t)
3807 return first;
3808 t = t1;
3809 }
3810 first = t+1;
3811 break;
3812 case 'L':
3813 // <expr-primary> or LZ <encoding> E
3814 if (first+1 != last && first[1] == 'Z')
3815 {
3816 t = parse_encoding(first+2, last, db);
3817 if (t != first+2 && t != last && *t == 'E')
3818 first = t+1;
3819 }
3820 else
3821 first = parse_expr_primary(first, last, db);
3822 break;
3823 default:
3824 // <type>
3825 first = parse_type(first, last, db);
3826 break;
3827 }
3828 }
3829 return first;
3830}
3831
3832// <template-args> ::= I <template-arg>* E
3833// extension, the abi says <template-arg>+
3834
3835template <class C>
3836const char*
3837parse_template_args(const char* first, const char* last, C& db)
3838{
3839 if (last - first >= 2 && *first == 'I')
3840 {
3841 if (db.tag_templates)
3842 db.template_param.back().clear();
3843 const char* t = first+1;
3844 typename C::String args("<");
3845 while (*t != 'E')
3846 {
3847 if (db.tag_templates)
3848 db.template_param.emplace_back(db.names.get_allocator());
3849 size_t k0 = db.names.size();
3850 const char* t1 = parse_template_arg(t, last, db);
3851 size_t k1 = db.names.size();
3852 if (db.tag_templates)
3853 db.template_param.pop_back();
3854 if (t1 == t || t1 == last)
3855 return first;
3856 if (db.tag_templates)
3857 {
3858 db.template_param.back().emplace_back(db.names.get_allocator());
3859 for (size_t k = k0; k < k1; ++k)
3860 db.template_param.back().back().push_back(db.names[k]);
3861 }
3862 for (size_t k = k0; k < k1; ++k)
3863 {
3864 if (args.size() > 1)
3865 args += ", ";
3866 args += db.names[k].move_full();
3867 }
3868 for (; k1 != k0; --k1)
3869 db.names.pop_back();
3870 t = t1;
3871 }
3872 first = t + 1;
3873 if (args.back() != '>')
3874 args += ">";
3875 else
3876 args += " >";
3877 db.names.push_back(std::move(args));
3878
3879 }
3880 return first;
3881}
3882
3883// <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
3884// ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
3885//
3886// <prefix> ::= <prefix> <unqualified-name>
3887// ::= <template-prefix> <template-args>
3888// ::= <template-param>
3889// ::= <decltype>
3890// ::= # empty
3891// ::= <substitution>
3892// ::= <prefix> <data-member-prefix>
3893// extension ::= L
3894//
3895// <template-prefix> ::= <prefix> <template unqualified-name>
3896// ::= <template-param>
3897// ::= <substitution>
3898
3899template <class C>
3900const char*
Richard Smith24ecd092014-05-12 18:44:13 +00003901parse_nested_name(const char* first, const char* last, C& db,
3902 bool* ends_with_template_args)
Howard Hinnant6c33e762013-06-17 18:10:34 +00003903{
3904 if (first != last && *first == 'N')
3905 {
3906 unsigned cv;
3907 const char* t0 = parse_cv_qualifiers(first+1, last, cv);
3908 if (t0 == last)
3909 return first;
3910 db.ref = 0;
3911 if (*t0 == 'R')
3912 {
3913 db.ref = 1;
3914 ++t0;
3915 }
3916 else if (*t0 == 'O')
3917 {
3918 db.ref = 2;
3919 ++t0;
3920 }
3921 db.names.emplace_back();
3922 if (last - t0 >= 2 && t0[0] == 'S' && t0[1] == 't')
3923 {
3924 t0 += 2;
3925 db.names.back().first = "std";
3926 }
3927 if (t0 == last)
3928 {
3929 db.names.pop_back();
3930 return first;
3931 }
3932 bool pop_subs = false;
Richard Smith24ecd092014-05-12 18:44:13 +00003933 bool component_ends_with_template_args = false;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003934 while (*t0 != 'E')
3935 {
Richard Smith24ecd092014-05-12 18:44:13 +00003936 component_ends_with_template_args = false;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003937 const char* t1;
3938 switch (*t0)
3939 {
3940 case 'S':
3941 if (t0 + 1 != last && t0[1] == 't')
3942 goto do_parse_unqualified_name;
3943 t1 = parse_substitution(t0, last, db);
3944 if (t1 != t0 && t1 != last)
3945 {
3946 auto name = db.names.back().move_full();
3947 db.names.pop_back();
3948 if (!db.names.back().first.empty())
3949 {
3950 db.names.back().first += "::" + name;
3951 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
3952 }
3953 else
3954 db.names.back().first = name;
3955 pop_subs = true;
3956 t0 = t1;
3957 }
3958 else
3959 return first;
3960 break;
3961 case 'T':
3962 t1 = parse_template_param(t0, last, db);
3963 if (t1 != t0 && t1 != last)
3964 {
3965 auto name = db.names.back().move_full();
3966 db.names.pop_back();
3967 if (!db.names.back().first.empty())
3968 db.names.back().first += "::" + name;
3969 else
3970 db.names.back().first = name;
3971 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
3972 pop_subs = true;
3973 t0 = t1;
3974 }
3975 else
3976 return first;
3977 break;
3978 case 'D':
3979 if (t0 + 1 != last && t0[1] != 't' && t0[1] != 'T')
3980 goto do_parse_unqualified_name;
3981 t1 = parse_decltype(t0, last, db);
3982 if (t1 != t0 && t1 != last)
3983 {
3984 auto name = db.names.back().move_full();
3985 db.names.pop_back();
3986 if (!db.names.back().first.empty())
3987 db.names.back().first += "::" + name;
3988 else
3989 db.names.back().first = name;
3990 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
3991 pop_subs = true;
3992 t0 = t1;
3993 }
3994 else
3995 return first;
3996 break;
3997 case 'I':
3998 t1 = parse_template_args(t0, last, db);
3999 if (t1 != t0 && t1 != last)
4000 {
4001 auto name = db.names.back().move_full();
4002 db.names.pop_back();
4003 db.names.back().first += name;
4004 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
4005 t0 = t1;
Richard Smith24ecd092014-05-12 18:44:13 +00004006 component_ends_with_template_args = true;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004007 }
4008 else
4009 return first;
4010 break;
4011 case 'L':
4012 if (++t0 == last)
4013 return first;
4014 break;
4015 default:
4016 do_parse_unqualified_name:
4017 t1 = parse_unqualified_name(t0, last, db);
4018 if (t1 != t0 && t1 != last)
4019 {
4020 auto name = db.names.back().move_full();
4021 db.names.pop_back();
4022 if (!db.names.back().first.empty())
4023 db.names.back().first += "::" + name;
4024 else
4025 db.names.back().first = name;
4026 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
4027 pop_subs = true;
4028 t0 = t1;
4029 }
4030 else
4031 return first;
4032 }
4033 }
4034 first = t0 + 1;
4035 db.cv = cv;
Howard Hinnantf6725172013-06-21 17:04:24 +00004036 if (pop_subs && !db.subs.empty())
Howard Hinnant6c33e762013-06-17 18:10:34 +00004037 db.subs.pop_back();
Richard Smith24ecd092014-05-12 18:44:13 +00004038 if (ends_with_template_args)
4039 *ends_with_template_args = component_ends_with_template_args;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004040 }
4041 return first;
4042}
4043
4044// <discriminator> := _ <non-negative number> # when number < 10
4045// := __ <non-negative number> _ # when number >= 10
4046// extension := decimal-digit+
4047
4048const char*
4049parse_discriminator(const char* first, const char* last)
4050{
4051 // parse but ignore discriminator
4052 if (first != last)
4053 {
4054 if (*first == '_')
4055 {
4056 const char* t1 = first+1;
4057 if (t1 != last)
4058 {
4059 if (std::isdigit(*t1))
4060 first = t1+1;
4061 else if (*t1 == '_')
4062 {
4063 for (++t1; t1 != last && std::isdigit(*t1); ++t1)
4064 ;
4065 if (t1 != last && *t1 == '_')
4066 first = t1 + 1;
4067 }
4068 }
4069 }
4070 else if (std::isdigit(*first))
4071 {
4072 const char* t1 = first+1;
4073 for (; t1 != last && std::isdigit(*t1); ++t1)
4074 ;
4075 first = t1;
4076 }
4077 }
4078 return first;
4079}
4080
4081// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
4082// := Z <function encoding> E s [<discriminator>]
4083// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
4084
4085template <class C>
4086const char*
Richard Smith24ecd092014-05-12 18:44:13 +00004087parse_local_name(const char* first, const char* last, C& db,
4088 bool* ends_with_template_args)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004089{
4090 if (first != last && *first == 'Z')
4091 {
4092 const char* t = parse_encoding(first+1, last, db);
4093 if (t != first+1 && t != last && *t == 'E' && ++t != last)
4094 {
4095 switch (*t)
4096 {
4097 case 's':
4098 first = parse_discriminator(t+1, last);
Howard Hinnant753a30d2013-12-11 19:44:25 +00004099 if (db.names.empty())
4100 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004101 db.names.back().first.append("::string literal");
4102 break;
4103 case 'd':
4104 if (++t != last)
4105 {
4106 const char* t1 = parse_number(t, last);
4107 if (t1 != last && *t1 == '_')
4108 {
4109 t = t1 + 1;
Richard Smith24ecd092014-05-12 18:44:13 +00004110 t1 = parse_name(t, last, db,
4111 ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004112 if (t1 != t)
4113 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004114 if (db.names.size() < 2)
4115 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004116 auto name = db.names.back().move_full();
4117 db.names.pop_back();
4118 db.names.back().first.append("::");
4119 db.names.back().first.append(name);
4120 first = t1;
4121 }
4122 else
4123 db.names.pop_back();
4124 }
4125 }
4126 break;
4127 default:
4128 {
Richard Smith24ecd092014-05-12 18:44:13 +00004129 const char* t1 = parse_name(t, last, db,
4130 ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004131 if (t1 != t)
4132 {
4133 // parse but ignore discriminator
4134 first = parse_discriminator(t1, last);
Howard Hinnant753a30d2013-12-11 19:44:25 +00004135 if (db.names.size() < 2)
4136 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004137 auto name = db.names.back().move_full();
4138 db.names.pop_back();
4139 db.names.back().first.append("::");
4140 db.names.back().first.append(name);
4141 }
4142 else
4143 db.names.pop_back();
4144 }
4145 break;
4146 }
4147 }
4148 }
4149 return first;
4150}
4151
4152// <name> ::= <nested-name> // N
4153// ::= <local-name> # See Scope Encoding below // Z
4154// ::= <unscoped-template-name> <template-args>
4155// ::= <unscoped-name>
4156
4157// <unscoped-template-name> ::= <unscoped-name>
4158// ::= <substitution>
4159
4160template <class C>
4161const char*
Richard Smith24ecd092014-05-12 18:44:13 +00004162parse_name(const char* first, const char* last, C& db,
4163 bool* ends_with_template_args)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004164{
4165 if (last - first >= 2)
4166 {
4167 const char* t0 = first;
4168 // extension: ignore L here
4169 if (*t0 == 'L')
4170 ++t0;
4171 switch (*t0)
4172 {
4173 case 'N':
4174 {
Richard Smith24ecd092014-05-12 18:44:13 +00004175 const char* t1 = parse_nested_name(t0, last, db,
4176 ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004177 if (t1 != t0)
4178 first = t1;
4179 break;
4180 }
4181 case 'Z':
4182 {
Richard Smith24ecd092014-05-12 18:44:13 +00004183 const char* t1 = parse_local_name(t0, last, db,
4184 ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004185 if (t1 != t0)
4186 first = t1;
4187 break;
4188 }
4189 default:
4190 {
4191 const char* t1 = parse_unscoped_name(t0, last, db);
4192 if (t1 != t0)
4193 {
4194 if (t1 != last && *t1 == 'I') // <unscoped-template-name> <template-args>
4195 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004196 if (db.names.empty())
4197 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004198 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
4199 t0 = t1;
4200 t1 = parse_template_args(t0, last, db);
4201 if (t1 != t0)
4202 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004203 if (db.names.size() < 2)
4204 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004205 auto tmp = db.names.back().move_full();
4206 db.names.pop_back();
4207 db.names.back().first += tmp;
4208 first = t1;
Richard Smith24ecd092014-05-12 18:44:13 +00004209 if (ends_with_template_args)
4210 *ends_with_template_args = true;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004211 }
4212 }
4213 else // <unscoped-name>
4214 first = t1;
4215 }
4216 else
4217 { // try <substitution> <template-args>
4218 t1 = parse_substitution(t0, last, db);
Howard Hinnantb4033ff2013-06-20 01:55:07 +00004219 if (t1 != t0 && t1 != last && *t1 == 'I')
Howard Hinnant6c33e762013-06-17 18:10:34 +00004220 {
4221 t0 = t1;
4222 t1 = parse_template_args(t0, last, db);
4223 if (t1 != t0)
4224 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004225 if (db.names.size() < 2)
4226 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004227 auto tmp = db.names.back().move_full();
4228 db.names.pop_back();
4229 db.names.back().first += tmp;
4230 first = t1;
Richard Smith24ecd092014-05-12 18:44:13 +00004231 if (ends_with_template_args)
4232 *ends_with_template_args = true;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004233 }
4234 }
4235 }
4236 break;
4237 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004238 }
4239 }
4240 return first;
4241}
4242
4243// <call-offset> ::= h <nv-offset> _
4244// ::= v <v-offset> _
4245//
4246// <nv-offset> ::= <offset number>
4247// # non-virtual base override
4248//
4249// <v-offset> ::= <offset number> _ <virtual offset number>
4250// # virtual base override, with vcall offset
4251
4252const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004253parse_call_offset(const char* first, const char* last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004254{
4255 if (first != last)
4256 {
4257 switch (*first)
4258 {
4259 case 'h':
4260 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004261 const char* t = parse_number(first + 1, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004262 if (t != first + 1 && t != last && *t == '_')
4263 first = t + 1;
4264 }
4265 break;
4266 case 'v':
4267 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004268 const char* t = parse_number(first + 1, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004269 if (t != first + 1 && t != last && *t == '_')
4270 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004271 const char* t2 = parse_number(++t, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004272 if (t2 != t && t2 != last && *t2 == '_')
4273 first = t2 + 1;
4274 }
4275 }
4276 break;
4277 }
4278 }
4279 return first;
4280}
4281
4282// <special-name> ::= TV <type> # virtual table
4283// ::= TT <type> # VTT structure (construction vtable index)
4284// ::= TI <type> # typeinfo structure
4285// ::= TS <type> # typeinfo name (null-terminated byte string)
4286// ::= Tc <call-offset> <call-offset> <base encoding>
4287// # base is the nominal target function of thunk
4288// # first call-offset is 'this' adjustment
4289// # second call-offset is result adjustment
4290// ::= T <call-offset> <base encoding>
4291// # base is the nominal target function of thunk
4292// ::= GV <object name> # Guard variable for one-time initialization
4293// # No <type>
Howard Hinnantf2700352011-12-09 20:07:56 +00004294// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
4295// extension ::= GR <object name> # reference temporary for object
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004296
Howard Hinnant6c33e762013-06-17 18:10:34 +00004297template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004298const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004299parse_special_name(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004300{
4301 if (last - first > 2)
4302 {
4303 const char* t;
4304 switch (*first)
4305 {
4306 case 'T':
4307 switch (first[1])
4308 {
4309 case 'V':
4310 // TV <type> # virtual table
Howard Hinnant6c33e762013-06-17 18:10:34 +00004311 t = parse_type(first+2, last, db);
4312 if (t != first+2)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004313 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004314 if (db.names.empty())
4315 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004316 db.names.back().first.insert(0, "vtable for ");
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004317 first = t;
4318 }
4319 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004320 case 'T':
4321 // TT <type> # VTT structure (construction vtable index)
4322 t = parse_type(first+2, last, db);
Howard Hinnantf2700352011-12-09 20:07:56 +00004323 if (t != first+2)
4324 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004325 if (db.names.empty())
4326 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004327 db.names.back().first.insert(0, "VTT for ");
4328 first = t;
4329 }
4330 break;
4331 case 'I':
4332 // TI <type> # typeinfo structure
4333 t = parse_type(first+2, last, db);
4334 if (t != first+2)
4335 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004336 if (db.names.empty())
4337 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004338 db.names.back().first.insert(0, "typeinfo for ");
4339 first = t;
4340 }
4341 break;
4342 case 'S':
4343 // TS <type> # typeinfo name (null-terminated byte string)
4344 t = parse_type(first+2, last, db);
4345 if (t != first+2)
4346 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004347 if (db.names.empty())
4348 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004349 db.names.back().first.insert(0, "typeinfo name for ");
4350 first = t;
4351 }
4352 break;
4353 case 'c':
4354 // Tc <call-offset> <call-offset> <base encoding>
4355 {
4356 const char* t0 = parse_call_offset(first+2, last);
4357 if (t0 == first+2)
4358 break;
4359 const char* t1 = parse_call_offset(t0, last);
4360 if (t1 == t0)
4361 break;
4362 t = parse_encoding(t1, last, db);
4363 if (t != t1)
4364 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004365 if (db.names.empty())
4366 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004367 db.names.back().first.insert(0, "covariant return thunk to ");
4368 first = t;
4369 }
4370 }
4371 break;
4372 case 'C':
4373 // extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
4374 t = parse_type(first+2, last, db);
4375 if (t != first+2)
4376 {
4377 const char* t0 = parse_number(t, last);
Howard Hinnantf2700352011-12-09 20:07:56 +00004378 if (t0 != t && t0 != last && *t0 == '_')
4379 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004380 const char* t1 = parse_type(++t0, last, db);
Howard Hinnantf2700352011-12-09 20:07:56 +00004381 if (t1 != t0)
4382 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004383 if (db.names.size() < 2)
4384 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004385 auto left = db.names.back().move_full();
4386 db.names.pop_back();
4387 db.names.back().first = "construction vtable for " +
4388 std::move(left) + "-in-" +
4389 db.names.back().move_full();
4390 first = t1;
Howard Hinnantf2700352011-12-09 20:07:56 +00004391 }
4392 }
4393 }
4394 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004395 default:
4396 // T <call-offset> <base encoding>
4397 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004398 const char* t0 = parse_call_offset(first+1, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004399 if (t0 == first+1)
4400 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004401 t = parse_encoding(t0, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004402 if (t != t0)
4403 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004404 if (db.names.empty())
4405 return first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004406 if (first[2] == 'v')
4407 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004408 db.names.back().first.insert(0, "virtual thunk to ");
4409 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004410 }
4411 else
4412 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004413 db.names.back().first.insert(0, "non-virtual thunk to ");
4414 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004415 }
4416 }
4417 }
4418 break;
4419 }
4420 break;
4421 case 'G':
Howard Hinnantf2700352011-12-09 20:07:56 +00004422 switch (first[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004423 {
Howard Hinnantf2700352011-12-09 20:07:56 +00004424 case 'V':
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004425 // GV <object name> # Guard variable for one-time initialization
Howard Hinnant6c33e762013-06-17 18:10:34 +00004426 t = parse_name(first+2, last, db);
4427 if (t != first+2)
4428 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004429 if (db.names.empty())
4430 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004431 db.names.back().first.insert(0, "guard variable for ");
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004432 first = t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004433 }
Howard Hinnantf2700352011-12-09 20:07:56 +00004434 break;
4435 case 'R':
4436 // extension ::= GR <object name> # reference temporary for object
Howard Hinnant6c33e762013-06-17 18:10:34 +00004437 t = parse_name(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004438 if (t != first+2)
4439 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004440 if (db.names.empty())
4441 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004442 db.names.back().first.insert(0, "reference temporary for ");
4443 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004444 }
4445 break;
4446 }
4447 break;
4448 }
4449 }
4450 return first;
4451}
4452
Howard Hinnant753a30d2013-12-11 19:44:25 +00004453template <class T>
4454class save_value
4455{
4456 T& restore_;
4457 T original_value_;
4458public:
4459 save_value(T& restore)
4460 : restore_(restore),
4461 original_value_(restore)
4462 {}
4463
4464 ~save_value()
4465 {
4466 restore_ = std::move(original_value_);
4467 }
4468
4469 save_value(const save_value&) = delete;
4470 save_value& operator=(const save_value&) = delete;
4471};
4472
Howard Hinnant6c33e762013-06-17 18:10:34 +00004473// <encoding> ::= <function name> <bare-function-type>
4474// ::= <data name>
4475// ::= <special-name>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004476
Howard Hinnant6c33e762013-06-17 18:10:34 +00004477template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004478const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004479parse_encoding(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004480{
4481 if (first != last)
4482 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004483 save_value<decltype(db.encoding_depth)> su(db.encoding_depth);
4484 ++db.encoding_depth;
4485 save_value<decltype(db.tag_templates)> sb(db.tag_templates);
4486 if (db.encoding_depth > 1)
4487 db.tag_templates = true;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004488 switch (*first)
4489 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004490 case 'G':
4491 case 'T':
4492 first = parse_special_name(first, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004493 break;
4494 default:
Howard Hinnant6c33e762013-06-17 18:10:34 +00004495 {
Richard Smith24ecd092014-05-12 18:44:13 +00004496 bool ends_with_template_args = false;
4497 const char* t = parse_name(first, last, db,
4498 &ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004499 unsigned cv = db.cv;
4500 unsigned ref = db.ref;
4501 if (t != first)
Howard Hinnantab87dcf2011-12-15 20:02:15 +00004502 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004503 if (t != last && *t != 'E' && *t != '.')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004504 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004505 save_value<bool> sb2(db.tag_templates);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004506 db.tag_templates = false;
4507 const char* t2;
4508 typename C::String ret2;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004509 if (db.names.empty())
4510 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004511 const typename C::String& nm = db.names.back().first;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004512 if (nm.empty())
4513 return first;
Richard Smith24ecd092014-05-12 18:44:13 +00004514 if (!db.parsed_ctor_dtor_cv && ends_with_template_args)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004515 {
4516 t2 = parse_type(t, last, db);
4517 if (t2 == t)
4518 return first;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004519 if (db.names.size() < 2)
4520 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004521 auto ret1 = std::move(db.names.back().first);
4522 ret2 = std::move(db.names.back().second);
4523 if (ret2.empty())
4524 ret1 += ' ';
4525 db.names.pop_back();
4526 db.names.back().first.insert(0, ret1);
4527 t = t2;
4528 }
4529 db.names.back().first += '(';
4530 if (t != last && *t == 'v')
4531 {
4532 ++t;
4533 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004534 else
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004535 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004536 bool first_arg = true;
4537 while (true)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004538 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004539 size_t k0 = db.names.size();
4540 t2 = parse_type(t, last, db);
4541 size_t k1 = db.names.size();
4542 if (t2 == t)
4543 break;
4544 if (k1 > k0)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004545 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004546 typename C::String tmp;
4547 for (size_t k = k0; k < k1; ++k)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004548 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004549 if (!tmp.empty())
4550 tmp += ", ";
4551 tmp += db.names[k].move_full();
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004552 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004553 for (size_t k = k0; k < k1; ++k)
4554 db.names.pop_back();
4555 if (!tmp.empty())
4556 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004557 if (db.names.empty())
4558 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004559 if (!first_arg)
4560 db.names.back().first += ", ";
4561 else
4562 first_arg = false;
4563 db.names.back().first += tmp;
4564 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004565 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004566 t = t2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004567 }
4568 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00004569 if (db.names.empty())
4570 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004571 db.names.back().first += ')';
4572 if (cv & 1)
4573 db.names.back().first.append(" const");
4574 if (cv & 2)
4575 db.names.back().first.append(" volatile");
4576 if (cv & 4)
4577 db.names.back().first.append(" restrict");
4578 if (ref == 1)
4579 db.names.back().first.append(" &");
4580 else if (ref == 2)
4581 db.names.back().first.append(" &&");
4582 db.names.back().first += ret2;
4583 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004584 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004585 else
4586 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004587 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004588 break;
4589 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004590 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004591 }
4592 return first;
4593}
4594
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004595// _block_invoke
4596// _block_invoke<decimal-digit>+
4597// _block_invoke_<decimal-digit>+
4598
Howard Hinnant6c33e762013-06-17 18:10:34 +00004599template <class C>
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004600const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004601parse_block_invoke(const char* first, const char* last, C& db)
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004602{
4603 if (last - first >= 13)
4604 {
4605 const char test[] = "_block_invoke";
4606 const char* t = first;
4607 for (int i = 0; i < 13; ++i, ++t)
4608 {
4609 if (*t != test[i])
4610 return first;
4611 }
4612 if (t != last)
4613 {
4614 if (*t == '_')
4615 {
4616 // must have at least 1 decimal digit
Howard Hinnant6c33e762013-06-17 18:10:34 +00004617 if (++t == last || !std::isdigit(*t))
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004618 return first;
4619 ++t;
4620 }
4621 // parse zero or more digits
4622 while (t != last && isdigit(*t))
4623 ++t;
4624 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00004625 if (db.names.empty())
4626 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004627 db.names.back().first.insert(0, "invocation function for block in ");
4628 first = t;
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004629 }
4630 return first;
4631}
4632
Howard Hinnant6c33e762013-06-17 18:10:34 +00004633// extension
4634// <dot-suffix> := .<anything and everything>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004635
Howard Hinnant6c33e762013-06-17 18:10:34 +00004636template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004637const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004638parse_dot_suffix(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004639{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004640 if (first != last && *first == '.')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004641 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004642 if (db.names.empty())
4643 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004644 db.names.back().first += " (" + typename C::String(first, last) + ")";
4645 first = last;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004646 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004647 return first;
4648}
4649
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004650// <block-involcaton-function> ___Z<encoding>_block_invoke
4651// <block-involcaton-function> ___Z<encoding>_block_invoke<decimal-digit>+
4652// <block-involcaton-function> ___Z<encoding>_block_invoke_<decimal-digit>+
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004653// <mangled-name> ::= _Z<encoding>
4654// ::= <type>
4655
Howard Hinnant6c33e762013-06-17 18:10:34 +00004656template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004657void
Howard Hinnant6c33e762013-06-17 18:10:34 +00004658demangle(const char* first, const char* last, C& db, int& status)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004659{
Howard Hinnanteb8d46c2013-06-23 17:14:35 +00004660 if (first >= last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004661 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004662 status = invalid_mangled_name;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004663 return;
4664 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004665 if (*first == '_')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004666 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004667 if (last - first >= 4)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004668 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004669 if (first[1] == 'Z')
4670 {
4671 const char* t = parse_encoding(first+2, last, db);
4672 if (t != first+2 && t != last && *t == '.')
4673 t = parse_dot_suffix(t, last, db);
4674 if (t != last)
4675 status = invalid_mangled_name;
4676 }
4677 else if (first[1] == '_' && first[2] == '_' && first[3] == 'Z')
4678 {
4679 const char* t = parse_encoding(first+4, last, db);
4680 if (t != first+4 && t != last)
4681 {
4682 const char* t1 = parse_block_invoke(t, last, db);
4683 if (t1 != last)
4684 status = invalid_mangled_name;
4685 }
4686 else
4687 status = invalid_mangled_name;
4688 }
4689 else
4690 status = invalid_mangled_name;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004691 }
4692 else
Howard Hinnant6c33e762013-06-17 18:10:34 +00004693 status = invalid_mangled_name;
4694 }
4695 else
4696 {
4697 const char* t = parse_type(first, last, db);
4698 if (t != last)
4699 status = invalid_mangled_name;
4700 }
Howard Hinnanteb8d46c2013-06-23 17:14:35 +00004701 if (status == success && db.names.empty())
4702 status = invalid_mangled_name;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004703}
4704
Howard Hinnant6c33e762013-06-17 18:10:34 +00004705template <std::size_t N>
4706class arena
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004707{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004708 static const std::size_t alignment = 16;
4709 alignas(alignment) char buf_[N];
4710 char* ptr_;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004711
Howard Hinnant6c33e762013-06-17 18:10:34 +00004712 std::size_t
4713 align_up(std::size_t n) noexcept
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +00004714 {return (n + (alignment-1)) & ~(alignment-1);}
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004715
Howard Hinnant6c33e762013-06-17 18:10:34 +00004716 bool
4717 pointer_in_buffer(char* p) noexcept
4718 {return buf_ <= p && p <= buf_ + N;}
4719
4720public:
4721 arena() noexcept : ptr_(buf_) {}
4722 ~arena() {ptr_ = nullptr;}
4723 arena(const arena&) = delete;
4724 arena& operator=(const arena&) = delete;
4725
4726 char* allocate(std::size_t n);
4727 void deallocate(char* p, std::size_t n) noexcept;
4728
4729 static constexpr std::size_t size() {return N;}
4730 std::size_t used() const {return static_cast<std::size_t>(ptr_ - buf_);}
4731 void reset() {ptr_ = buf_;}
4732};
4733
4734template <std::size_t N>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004735char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004736arena<N>::allocate(std::size_t n)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004737{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004738 n = align_up(n);
4739 if (static_cast<std::size_t>(buf_ + N - ptr_) >= n)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004740 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004741 char* r = ptr_;
4742 ptr_ += n;
4743 return r;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004744 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004745 return static_cast<char*>(std::malloc(n));
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004746}
4747
Howard Hinnant6c33e762013-06-17 18:10:34 +00004748template <std::size_t N>
4749void
4750arena<N>::deallocate(char* p, std::size_t n) noexcept
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004751{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004752 if (pointer_in_buffer(p))
4753 {
4754 n = align_up(n);
4755 if (p + n == ptr_)
4756 ptr_ = p;
4757 }
4758 else
4759 std::free(p);
4760}
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004761
Howard Hinnant6c33e762013-06-17 18:10:34 +00004762template <class T, std::size_t N>
4763class short_alloc
4764{
4765 arena<N>& a_;
4766public:
4767 typedef T value_type;
4768
4769public:
4770 template <class _Up> struct rebind {typedef short_alloc<_Up, N> other;};
4771
4772 short_alloc(arena<N>& a) noexcept : a_(a) {}
4773 template <class U>
4774 short_alloc(const short_alloc<U, N>& a) noexcept
4775 : a_(a.a_) {}
4776 short_alloc(const short_alloc&) = default;
4777 short_alloc& operator=(const short_alloc&) = delete;
4778
4779 T* allocate(std::size_t n)
4780 {
4781 return reinterpret_cast<T*>(a_.allocate(n*sizeof(T)));
4782 }
4783 void deallocate(T* p, std::size_t n) noexcept
4784 {
4785 a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
4786 }
4787
4788 template <class T1, std::size_t N1, class U, std::size_t M>
4789 friend
4790 bool
4791 operator==(const short_alloc<T1, N1>& x, const short_alloc<U, M>& y) noexcept;
4792
4793 template <class U, std::size_t M> friend class short_alloc;
4794};
4795
4796template <class T, std::size_t N, class U, std::size_t M>
4797inline
4798bool
4799operator==(const short_alloc<T, N>& x, const short_alloc<U, M>& y) noexcept
4800{
4801 return N == M && &x.a_ == &y.a_;
4802}
4803
4804template <class T, std::size_t N, class U, std::size_t M>
4805inline
4806bool
4807operator!=(const short_alloc<T, N>& x, const short_alloc<U, M>& y) noexcept
4808{
4809 return !(x == y);
4810}
4811
4812template <class T>
4813class malloc_alloc
4814{
4815public:
4816 typedef T value_type;
4817
4818 malloc_alloc() = default;
4819 template <class U> malloc_alloc(const malloc_alloc<U>&) noexcept {}
4820
4821 T* allocate(std::size_t n)
4822 {
4823 return static_cast<T*>(std::malloc(n*sizeof(T)));
4824 }
4825 void deallocate(T* p, std::size_t) noexcept
4826 {
4827 std::free(p);
4828 }
4829};
4830
4831template <class T, class U>
4832inline
4833bool
4834operator==(const malloc_alloc<T>&, const malloc_alloc<U>&) noexcept
4835{
4836 return true;
4837}
4838
4839template <class T, class U>
4840inline
4841bool
4842operator!=(const malloc_alloc<T>& x, const malloc_alloc<U>& y) noexcept
4843{
4844 return !(x == y);
4845}
4846
4847const size_t bs = 4 * 1024;
4848template <class T> using Alloc = short_alloc<T, bs>;
4849template <class T> using Vector = std::vector<T, Alloc<T>>;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004850
Nico Weber2b683fb2014-05-30 17:27:21 +00004851template <class StrT>
Howard Hinnant6c33e762013-06-17 18:10:34 +00004852struct string_pair
4853{
Nico Weber2b683fb2014-05-30 17:27:21 +00004854 StrT first;
4855 StrT second;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004856
4857 string_pair() = default;
Nico Weber2b683fb2014-05-30 17:27:21 +00004858 string_pair(StrT f) : first(std::move(f)) {}
4859 string_pair(StrT f, StrT s)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004860 : first(std::move(f)), second(std::move(s)) {}
4861 template <size_t N>
4862 string_pair(const char (&s)[N]) : first(s, N-1) {}
4863
4864 size_t size() const {return first.size() + second.size();}
Nico Weber2b683fb2014-05-30 17:27:21 +00004865 StrT full() const {return first + second;}
4866 StrT move_full() {return std::move(first) + std::move(second);}
Howard Hinnant6c33e762013-06-17 18:10:34 +00004867};
4868
Howard Hinnant061240c2013-10-22 16:45:48 +00004869struct Db
4870{
Nico Weber2b683fb2014-05-30 17:27:21 +00004871 typedef std::basic_string<char, std::char_traits<char>,
4872 malloc_alloc<char>> String;
4873 typedef Vector<string_pair<String>> sub_type;
Howard Hinnant061240c2013-10-22 16:45:48 +00004874 typedef Vector<sub_type> template_param_type;
Nico Weber2b683fb2014-05-30 17:27:21 +00004875 sub_type names;
4876 template_param_type subs;
Howard Hinnant061240c2013-10-22 16:45:48 +00004877 Vector<template_param_type> template_param;
4878 unsigned cv;
4879 unsigned ref;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004880 unsigned encoding_depth;
Howard Hinnant061240c2013-10-22 16:45:48 +00004881 bool parsed_ctor_dtor_cv;
4882 bool tag_templates;
4883 bool fix_forward_references;
4884 bool try_to_parse_template_args;
4885
4886 template <size_t N>
4887 Db(arena<N>& ar) :
4888 names(ar),
4889 subs(0, names, ar),
4890 template_param(0, subs, ar)
4891 {}
4892};
4893
Howard Hinnant6c33e762013-06-17 18:10:34 +00004894} // unnamed namespace
4895
Howard Hinnant6c33e762013-06-17 18:10:34 +00004896extern "C"
Nico Weber298baa32014-06-25 23:55:37 +00004897__attribute__ ((__visibility__("default")))
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004898char*
4899__cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status)
4900{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004901 if (mangled_name == nullptr || (buf != nullptr && n == nullptr))
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004902 {
4903 if (status)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004904 *status = invalid_args;
4905 return nullptr;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004906 }
Howard Hinnant8ad6a222013-07-26 22:14:53 +00004907 size_t internal_size = buf != nullptr ? *n : 0;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004908 arena<bs> a;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004909 Db db(a);
4910 db.cv = 0;
Howard Hinnant19e36dd2013-06-19 13:43:18 +00004911 db.ref = 0;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004912 db.encoding_depth = 0;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004913 db.parsed_ctor_dtor_cv = false;
4914 db.tag_templates = true;
4915 db.template_param.emplace_back(a);
4916 db.fix_forward_references = false;
4917 db.try_to_parse_template_args = true;
4918 int internal_status = success;
Howard Hinnantb2d1f942013-06-23 19:52:45 +00004919 size_t len = std::strlen(mangled_name);
4920 demangle(mangled_name, mangled_name + len, db,
Howard Hinnant6c33e762013-06-17 18:10:34 +00004921 internal_status);
Howard Hinnantb2d1f942013-06-23 19:52:45 +00004922 if (internal_status == success && db.fix_forward_references &&
4923 !db.template_param.empty() && !db.template_param.front().empty())
4924 {
4925 db.fix_forward_references = false;
4926 db.tag_templates = false;
4927 db.names.clear();
4928 db.subs.clear();
4929 demangle(mangled_name, mangled_name + len, db, internal_status);
4930 if (db.fix_forward_references)
4931 internal_status = invalid_mangled_name;
4932 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004933 if (internal_status == success)
4934 {
4935 size_t sz = db.names.back().size() + 1;
4936 if (sz > internal_size)
4937 {
4938 char* newbuf = static_cast<char*>(std::realloc(buf, sz));
4939 if (newbuf == nullptr)
4940 {
4941 internal_status = memory_alloc_failure;
4942 buf = nullptr;
4943 }
4944 else
Howard Hinnant8ad6a222013-07-26 22:14:53 +00004945 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004946 buf = newbuf;
Howard Hinnant8ad6a222013-07-26 22:14:53 +00004947 if (n != nullptr)
4948 *n = sz;
4949 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004950 }
4951 if (buf != nullptr)
4952 {
4953 db.names.back().first += db.names.back().second;
4954 std::memcpy(buf, db.names.back().first.data(), sz-1);
4955 buf[sz-1] = char(0);
4956 }
4957 }
4958 else
4959 buf = nullptr;
4960 if (status)
4961 *status = internal_status;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004962 return buf;
4963}
4964
Howard Hinnant6c33e762013-06-17 18:10:34 +00004965} // __cxxabiv1