blob: d80843e3eb1a0aaed446ec0b2e07d8467f6d738f [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 {
Saleem Abdulrasool2493be62015-04-27 02:21:52 +0000198#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
Howard Hinnant6c33e762013-06-17 18:10:34 +0000199 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 if (*t == 'Y')
1579 {
Saleem Abdulrasoolb2cceca2015-04-27 02:21:57 +00001580 /* extern "C" */
Howard Hinnant6c33e762013-06-17 18:10:34 +00001581 if (++t == last)
1582 return first;
1583 }
1584 const char* t1 = parse_type(t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001585 if (t1 != t)
1586 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001587 t = t1;
1588 typename C::String sig("(");
1589 int ref_qual = 0;
1590 while (true)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001591 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001592 if (t == last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001593 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001594 db.names.pop_back();
1595 return first;
1596 }
1597 if (*t == 'E')
1598 {
1599 ++t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001600 break;
1601 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001602 if (*t == 'v')
1603 {
1604 ++t;
1605 continue;
1606 }
1607 if (*t == 'R' && t+1 != last && t[1] == 'E')
1608 {
1609 ref_qual = 1;
1610 ++t;
1611 continue;
1612 }
1613 if (*t == 'O' && t+1 != last && t[1] == 'E')
1614 {
1615 ref_qual = 2;
1616 ++t;
1617 continue;
1618 }
1619 size_t k0 = db.names.size();
1620 t1 = parse_type(t, last, db);
1621 size_t k1 = db.names.size();
1622 if (t1 == t || t1 == last)
1623 return first;
1624 for (size_t k = k0; k < k1; ++k)
1625 {
1626 if (sig.size() > 1)
1627 sig += ", ";
1628 sig += db.names[k].move_full();
1629 }
1630 for (size_t k = k0; k < k1; ++k)
1631 db.names.pop_back();
1632 t = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001633 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001634 sig += ")";
1635 switch (ref_qual)
1636 {
1637 case 1:
1638 sig += " &";
1639 break;
1640 case 2:
1641 sig += " &&";
1642 break;
1643 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00001644 if (db.names.empty())
1645 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001646 db.names.back().first += " ";
1647 db.names.back().second.insert(0, sig);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001648 first = t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001649 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001650 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001651 }
1652 return first;
1653}
1654
1655// <pointer-to-member-type> ::= M <class type> <member type>
1656
1657template <class C>
1658const char*
1659parse_pointer_to_member_type(const char* first, const char* last, C& db)
1660{
1661 if (first != last && *first == 'M')
1662 {
1663 const char* t = parse_type(first+1, last, db);
1664 if (t != first+1)
1665 {
1666 const char* t2 = parse_type(t, last, db);
1667 if (t2 != t)
1668 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001669 if (db.names.size() < 2)
1670 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001671 auto func = std::move(db.names.back());
1672 db.names.pop_back();
1673 auto class_type = std::move(db.names.back());
Chaoren Lin3b8762a2015-05-26 23:14:26 +00001674 if (!func.second.empty() && func.second.front() == '(')
Howard Hinnant6c33e762013-06-17 18:10:34 +00001675 {
1676 db.names.back().first = std::move(func.first) + "(" + class_type.move_full() + "::*";
1677 db.names.back().second = ")" + std::move(func.second);
1678 }
1679 else
1680 {
1681 db.names.back().first = std::move(func.first) + " " + class_type.move_full() + "::*";
1682 db.names.back().second = std::move(func.second);
1683 }
1684 first = t2;
1685 }
1686 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001687 }
1688 return first;
1689}
1690
1691// <array-type> ::= A <positive dimension number> _ <element type>
1692// ::= A [<dimension expression>] _ <element type>
1693
Howard Hinnant6c33e762013-06-17 18:10:34 +00001694template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001695const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001696parse_array_type(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001697{
1698 if (first != last && *first == 'A' && first+1 != last)
1699 {
1700 if (first[1] == '_')
1701 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001702 const char* t = parse_type(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001703 if (t != first+2)
1704 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001705 if (db.names.empty())
1706 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001707 if (db.names.back().second.substr(0, 2) == " [")
1708 db.names.back().second.erase(0, 1);
1709 db.names.back().second.insert(0, " []");
1710 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001711 }
1712 }
1713 else if ('1' <= first[1] && first[1] <= '9')
1714 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001715 const char* t = parse_number(first+1, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001716 if (t != last && *t == '_')
1717 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001718 const char* t2 = parse_type(t+1, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001719 if (t2 != t+1)
1720 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001721 if (db.names.empty())
1722 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001723 if (db.names.back().second.substr(0, 2) == " [")
1724 db.names.back().second.erase(0, 1);
1725 db.names.back().second.insert(0, " [" + typename C::String(first+1, t) + "]");
1726 first = t2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001727 }
1728 }
1729 }
1730 else
1731 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001732 const char* t = parse_expression(first+1, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001733 if (t != first+1 && t != last && *t == '_')
1734 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001735 const char* t2 = parse_type(++t, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001736 if (t2 != t)
1737 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001738 if (db.names.size() < 2)
1739 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001740 auto type = std::move(db.names.back());
1741 db.names.pop_back();
1742 auto expr = std::move(db.names.back());
1743 db.names.back().first = std::move(type.first);
1744 if (type.second.substr(0, 2) == " [")
1745 type.second.erase(0, 1);
1746 db.names.back().second = " [" + expr.move_full() + "]" + std::move(type.second);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001747 first = t2;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001748 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001749 }
1750 }
1751 }
1752 return first;
1753}
1754
1755// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
1756// ::= DT <expression> E # decltype of an expression (C++0x)
1757
Howard Hinnant6c33e762013-06-17 18:10:34 +00001758template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001759const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001760parse_decltype(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001761{
1762 if (last - first >= 4 && first[0] == 'D')
1763 {
1764 switch (first[1])
1765 {
1766 case 't':
1767 case 'T':
1768 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001769 const char* t = parse_expression(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001770 if (t != first+2 && t != last && *t == 'E')
1771 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001772 if (db.names.empty())
1773 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001774 db.names.back() = "decltype(" + db.names.back().move_full() + ")";
1775 first = t+1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001776 }
1777 }
1778 break;
1779 }
1780 }
1781 return first;
1782}
1783
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001784// extension:
1785// <vector-type> ::= Dv <positive dimension number> _
1786// <extended element type>
1787// ::= Dv [<dimension expression>] _ <element type>
1788// <extended element type> ::= <element type>
1789// ::= p # AltiVec vector pixel
1790
Howard Hinnant6c33e762013-06-17 18:10:34 +00001791template <class C>
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001792const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001793parse_vector_type(const char* first, const char* last, C& db)
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001794{
1795 if (last - first > 3 && first[0] == 'D' && first[1] == 'v')
1796 {
1797 if ('1' <= first[2] && first[2] <= '9')
1798 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001799 const char* t = parse_number(first+2, last);
1800 if (t == last || *t != '_')
1801 return first;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001802 const char* num = first + 2;
Howard Hinnant3e5c7d02012-03-08 18:45:24 +00001803 size_t sz = static_cast<size_t>(t - num);
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001804 if (++t != last)
1805 {
1806 if (*t != 'p')
1807 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001808 const char* t1 = parse_type(t, last, db);
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001809 if (t1 != t)
1810 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001811 if (db.names.empty())
1812 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001813 db.names.back().first += " vector[" + typename C::String(num, sz) + "]";
1814 first = t1;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001815 }
1816 }
1817 else
1818 {
1819 ++t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001820 db.names.push_back("pixel vector[" + typename C::String(num, sz) + "]");
1821 first = t;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001822 }
1823 }
1824 }
1825 else
1826 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001827 typename C::String num;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001828 const char* t1 = first+2;
1829 if (*t1 != '_')
1830 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001831 const char* t = parse_expression(t1, last, db);
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001832 if (t != t1)
Howard Hinnant6c33e762013-06-17 18:10:34 +00001833 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001834 if (db.names.empty())
1835 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001836 num = db.names.back().move_full();
1837 db.names.pop_back();
1838 t1 = t;
1839 }
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001840 }
1841 if (t1 != last && *t1 == '_' && ++t1 != last)
1842 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001843 const char* t = parse_type(t1, last, db);
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001844 if (t != t1)
1845 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001846 if (db.names.empty())
1847 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001848 db.names.back().first += " vector[" + num + "]";
1849 first = t;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001850 }
1851 }
1852 }
1853 }
1854 return first;
1855}
1856
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001857// <type> ::= <builtin-type>
1858// ::= <function-type>
1859// ::= <class-enum-type>
1860// ::= <array-type>
1861// ::= <pointer-to-member-type>
1862// ::= <template-param>
1863// ::= <template-template-param> <template-args>
1864// ::= <decltype>
1865// ::= <substitution>
1866// ::= <CV-qualifiers> <type>
1867// ::= P <type> # pointer-to
1868// ::= R <type> # reference-to
1869// ::= O <type> # rvalue reference-to (C++0x)
1870// ::= C <type> # complex pair (C 2000)
1871// ::= G <type> # imaginary (C 2000)
1872// ::= Dp <type> # pack expansion (C++0x)
1873// ::= U <source-name> <type> # vendor extended type qualifier
Howard Hinnant19e36dd2013-06-19 13:43:18 +00001874// extension := U <objc-name> <objc-type> # objc-type<identifier>
Howard Hinnantab87dcf2011-12-15 20:02:15 +00001875// extension := <vector-type> # <vector-type> starts with Dv
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001876
Howard Hinnant19e36dd2013-06-19 13:43:18 +00001877// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
1878// <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
1879
Howard Hinnant6c33e762013-06-17 18:10:34 +00001880template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001881const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00001882parse_type(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001883{
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001884 if (first != last)
1885 {
1886 switch (*first)
1887 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001888 case 'r':
1889 case 'V':
1890 case 'K':
1891 {
1892 unsigned cv = 0;
1893 const char* t = parse_cv_qualifiers(first, last, cv);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001894 if (t != first)
1895 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001896 bool is_function = *t == 'F';
1897 size_t k0 = db.names.size();
1898 const char* t1 = parse_type(t, last, db);
1899 size_t k1 = db.names.size();
1900 if (t1 != t)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001901 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001902 if (is_function)
1903 db.subs.pop_back();
1904 db.subs.emplace_back(db.names.get_allocator());
1905 for (size_t k = k0; k < k1; ++k)
1906 {
1907 if (is_function)
1908 {
1909 size_t p = db.names[k].second.size();
1910 if (db.names[k].second[p-2] == '&')
1911 p -= 3;
1912 else if (db.names[k].second.back() == '&')
1913 p -= 2;
1914 if (cv & 1)
1915 {
1916 db.names[k].second.insert(p, " const");
1917 p += 6;
1918 }
1919 if (cv & 2)
1920 {
1921 db.names[k].second.insert(p, " volatile");
1922 p += 9;
1923 }
1924 if (cv & 4)
1925 db.names[k].second.insert(p, " restrict");
1926 }
1927 else
1928 {
1929 if (cv & 1)
1930 db.names[k].first.append(" const");
1931 if (cv & 2)
1932 db.names[k].first.append(" volatile");
1933 if (cv & 4)
1934 db.names[k].first.append(" restrict");
1935 }
1936 db.subs.back().push_back(db.names[k]);
1937 }
1938 first = t1;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001939 }
1940 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00001941 }
1942 break;
1943 default:
1944 {
1945 const char* t = parse_builtin_type(first, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001946 if (t != first)
1947 {
1948 first = t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001949 }
1950 else
1951 {
1952 switch (*first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001953 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00001954 case 'A':
1955 t = parse_array_type(first, last, db);
1956 if (t != first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00001957 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001958 if (db.names.empty())
1959 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001960 first = t;
1961 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
1962 }
1963 break;
1964 case 'C':
1965 t = parse_type(first+1, last, db);
1966 if (t != first+1)
1967 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001968 if (db.names.empty())
1969 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001970 db.names.back().first.append(" complex");
1971 first = t;
1972 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
1973 }
1974 break;
1975 case 'F':
1976 t = parse_function_type(first, last, db);
1977 if (t != first)
1978 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001979 if (db.names.empty())
1980 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001981 first = t;
1982 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
1983 }
1984 break;
1985 case 'G':
1986 t = parse_type(first+1, last, db);
1987 if (t != first+1)
1988 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00001989 if (db.names.empty())
1990 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00001991 db.names.back().first.append(" imaginary");
1992 first = t;
1993 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
1994 }
1995 break;
1996 case 'M':
1997 t = parse_pointer_to_member_type(first, last, db);
1998 if (t != first)
1999 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002000 if (db.names.empty())
2001 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002002 first = t;
2003 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2004 }
2005 break;
2006 case 'O':
2007 {
2008 size_t k0 = db.names.size();
2009 t = parse_type(first+1, last, db);
2010 size_t k1 = db.names.size();
2011 if (t != first+1)
2012 {
2013 db.subs.emplace_back(db.names.get_allocator());
2014 for (size_t k = k0; k < k1; ++k)
2015 {
2016 if (db.names[k].second.substr(0, 2) == " [")
2017 {
2018 db.names[k].first += " (";
2019 db.names[k].second.insert(0, ")");
2020 }
Chaoren Lin3b8762a2015-05-26 23:14:26 +00002021 else if (!db.names[k].second.empty() &&
2022 db.names[k].second.front() == '(')
Howard Hinnant6c33e762013-06-17 18:10:34 +00002023 {
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 }
Chaoren Lin3b8762a2015-05-26 23:14:26 +00002049 else if (!db.names[k].second.empty() &&
2050 db.names[k].second.front() == '(')
Howard Hinnant6c33e762013-06-17 18:10:34 +00002051 {
2052 db.names[k].first += "(";
2053 db.names[k].second.insert(0, ")");
2054 }
Howard Hinnant19e36dd2013-06-19 13:43:18 +00002055 if (first[1] != 'U' || db.names[k].first.substr(0, 12) != "objc_object<")
2056 {
2057 db.names[k].first.append("*");
2058 }
2059 else
2060 {
2061 db.names[k].first.replace(0, 11, "id");
2062 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002063 db.subs.back().push_back(db.names[k]);
2064 }
2065 first = t;
2066 }
2067 break;
2068 }
2069 case 'R':
2070 {
2071 size_t k0 = db.names.size();
2072 t = parse_type(first+1, last, db);
2073 size_t k1 = db.names.size();
2074 if (t != first+1)
2075 {
2076 db.subs.emplace_back(db.names.get_allocator());
2077 for (size_t k = k0; k < k1; ++k)
2078 {
2079 if (db.names[k].second.substr(0, 2) == " [")
2080 {
2081 db.names[k].first += " (";
2082 db.names[k].second.insert(0, ")");
2083 }
Chaoren Lin3b8762a2015-05-26 23:14:26 +00002084 else if (!db.names[k].second.empty() &&
2085 db.names[k].second.front() == '(')
Howard Hinnant6c33e762013-06-17 18:10:34 +00002086 {
2087 db.names[k].first += "(";
2088 db.names[k].second.insert(0, ")");
2089 }
2090 db.names[k].first.append("&");
2091 db.subs.back().push_back(db.names[k]);
2092 }
2093 first = t;
2094 }
2095 break;
2096 }
2097 case 'T':
2098 {
2099 size_t k0 = db.names.size();
2100 t = parse_template_param(first, last, db);
2101 size_t k1 = db.names.size();
2102 if (t != first)
2103 {
2104 db.subs.emplace_back(db.names.get_allocator());
2105 for (size_t k = k0; k < k1; ++k)
2106 db.subs.back().push_back(db.names[k]);
2107 if (db.try_to_parse_template_args && k1 == k0+1)
2108 {
2109 const char* t1 = parse_template_args(t, last, db);
2110 if (t1 != t)
2111 {
2112 auto args = db.names.back().move_full();
2113 db.names.pop_back();
2114 db.names.back().first += std::move(args);
2115 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2116 t = t1;
2117 }
2118 }
2119 first = t;
2120 }
2121 break;
2122 }
2123 case 'U':
2124 if (first+1 != last)
2125 {
2126 t = parse_source_name(first+1, last, db);
2127 if (t != first+1)
2128 {
2129 const char* t2 = parse_type(t, last, db);
2130 if (t2 != t)
2131 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002132 if (db.names.size() < 2)
2133 return first;
Howard Hinnant19e36dd2013-06-19 13:43:18 +00002134 auto type = db.names.back().move_full();
Howard Hinnant6c33e762013-06-17 18:10:34 +00002135 db.names.pop_back();
Howard Hinnant19e36dd2013-06-19 13:43:18 +00002136 if (db.names.back().first.substr(0, 9) != "objcproto")
2137 {
2138 db.names.back() = type + " " + db.names.back().move_full();
2139 }
2140 else
2141 {
2142 auto proto = db.names.back().move_full();
2143 db.names.pop_back();
2144 t = parse_source_name(proto.data() + 9, proto.data() + proto.size(), db);
2145 if (t != proto.data() + 9)
2146 {
2147 db.names.back() = type + "<" + db.names.back().move_full() + ">";
2148 }
2149 else
2150 {
2151 db.names.push_back(type + " " + proto);
2152 }
2153 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002154 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2155 first = t2;
2156 }
2157 }
2158 }
2159 break;
2160 case 'S':
2161 if (first+1 != last && first[1] == 't')
2162 {
2163 t = parse_name(first, last, db);
2164 if (t != first)
2165 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002166 if (db.names.empty())
2167 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002168 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002169 first = t;
2170 }
2171 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002172 else
2173 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002174 t = parse_substitution(first, last, db);
2175 if (t != first)
2176 {
2177 first = t;
2178 // Parsed a substitution. If the substitution is a
2179 // <template-param> it might be followed by <template-args>.
2180 t = parse_template_args(first, last, db);
2181 if (t != first)
2182 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002183 if (db.names.size() < 2)
2184 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002185 auto template_args = db.names.back().move_full();
2186 db.names.pop_back();
2187 db.names.back().first += template_args;
2188 // Need to create substitution for <template-template-param> <template-args>
2189 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2190 first = t;
2191 }
2192 }
2193 }
2194 break;
2195 case 'D':
2196 if (first+1 != last)
2197 {
2198 switch (first[1])
2199 {
2200 case 'p':
2201 {
2202 size_t k0 = db.names.size();
2203 t = parse_type(first+2, last, db);
2204 size_t k1 = db.names.size();
Howard Hinnantf6725172013-06-21 17:04:24 +00002205 if (t != first+2)
Howard Hinnant6c33e762013-06-17 18:10:34 +00002206 {
2207 db.subs.emplace_back(db.names.get_allocator());
2208 for (size_t k = k0; k < k1; ++k)
2209 db.subs.back().push_back(db.names[k]);
2210 first = t;
2211 return first;
2212 }
2213 break;
2214 }
2215 case 't':
2216 case 'T':
2217 t = parse_decltype(first, last, db);
2218 if (t != first)
2219 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002220 if (db.names.empty())
2221 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002222 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2223 first = t;
2224 return first;
2225 }
2226 break;
2227 case 'v':
2228 t = parse_vector_type(first, last, db);
2229 if (t != first)
2230 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002231 if (db.names.empty())
2232 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002233 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2234 first = t;
2235 return first;
2236 }
2237 break;
2238 }
2239 }
2240 // drop through
2241 default:
2242 // must check for builtin-types before class-enum-types to avoid
2243 // ambiguities with operator-names
2244 t = parse_builtin_type(first, last, db);
2245 if (t != first)
2246 {
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002247 first = t;
2248 }
Howard Hinnantab87dcf2011-12-15 20:02:15 +00002249 else
2250 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002251 t = parse_name(first, last, db);
2252 if (t != first)
2253 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002254 if (db.names.empty())
2255 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002256 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
2257 first = t;
2258 }
Howard Hinnantab87dcf2011-12-15 20:02:15 +00002259 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002260 break;
Howard Hinnantab87dcf2011-12-15 20:02:15 +00002261 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002262 }
2263 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002264 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002265 }
2266 }
2267 return first;
2268}
2269
2270// <operator-name>
2271// ::= aa # &&
2272// ::= ad # & (unary)
2273// ::= an # &
2274// ::= aN # &=
2275// ::= aS # =
2276// ::= cl # ()
2277// ::= cm # ,
2278// ::= co # ~
2279// ::= cv <type> # (cast)
2280// ::= da # delete[]
2281// ::= de # * (unary)
2282// ::= dl # delete
2283// ::= dv # /
2284// ::= dV # /=
2285// ::= eo # ^
2286// ::= eO # ^=
2287// ::= eq # ==
2288// ::= ge # >=
2289// ::= gt # >
2290// ::= ix # []
2291// ::= le # <=
Howard Hinnantf29757a2014-01-06 23:05:04 +00002292// ::= li <source-name> # operator ""
Howard Hinnant6c33e762013-06-17 18:10:34 +00002293// ::= ls # <<
2294// ::= lS # <<=
2295// ::= lt # <
2296// ::= mi # -
2297// ::= mI # -=
2298// ::= ml # *
2299// ::= mL # *=
2300// ::= mm # -- (postfix in <expression> context)
2301// ::= na # new[]
2302// ::= ne # !=
2303// ::= ng # - (unary)
2304// ::= nt # !
2305// ::= nw # new
2306// ::= oo # ||
2307// ::= or # |
2308// ::= oR # |=
2309// ::= pm # ->*
2310// ::= pl # +
2311// ::= pL # +=
2312// ::= pp # ++ (postfix in <expression> context)
2313// ::= ps # + (unary)
2314// ::= pt # ->
2315// ::= qu # ?
2316// ::= rm # %
2317// ::= rM # %=
2318// ::= rs # >>
2319// ::= rS # >>=
2320// ::= v <digit> <source-name> # vendor extended operator
2321
2322template <class C>
2323const char*
2324parse_operator_name(const char* first, const char* last, C& db)
2325{
2326 if (last - first >= 2)
2327 {
2328 switch (first[0])
2329 {
2330 case 'a':
2331 switch (first[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002332 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002333 case 'a':
2334 db.names.push_back("operator&&");
2335 first += 2;
2336 break;
2337 case 'd':
2338 case 'n':
2339 db.names.push_back("operator&");
2340 first += 2;
2341 break;
2342 case 'N':
2343 db.names.push_back("operator&=");
2344 first += 2;
2345 break;
2346 case 'S':
2347 db.names.push_back("operator=");
2348 first += 2;
2349 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002350 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002351 break;
2352 case 'c':
2353 switch (first[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002354 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002355 case 'l':
2356 db.names.push_back("operator()");
2357 first += 2;
2358 break;
2359 case 'm':
2360 db.names.push_back("operator,");
2361 first += 2;
2362 break;
2363 case 'o':
2364 db.names.push_back("operator~");
2365 first += 2;
2366 break;
2367 case 'v':
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002368 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00002369 bool try_to_parse_template_args = db.try_to_parse_template_args;
2370 db.try_to_parse_template_args = false;
2371 const char* t = parse_type(first+2, last, db);
2372 db.try_to_parse_template_args = try_to_parse_template_args;
2373 if (t != first+2)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002374 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002375 if (db.names.empty())
2376 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002377 db.names.back().first.insert(0, "operator ");
2378 db.parsed_ctor_dtor_cv = true;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002379 first = t;
2380 }
2381 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00002382 break;
2383 }
2384 break;
2385 case 'd':
2386 switch (first[1])
2387 {
2388 case 'a':
2389 db.names.push_back("operator delete[]");
2390 first += 2;
2391 break;
2392 case 'e':
2393 db.names.push_back("operator*");
2394 first += 2;
2395 break;
2396 case 'l':
2397 db.names.push_back("operator delete");
2398 first += 2;
2399 break;
2400 case 'v':
2401 db.names.push_back("operator/");
2402 first += 2;
2403 break;
2404 case 'V':
2405 db.names.push_back("operator/=");
2406 first += 2;
2407 break;
2408 }
2409 break;
2410 case 'e':
2411 switch (first[1])
2412 {
2413 case 'o':
2414 db.names.push_back("operator^");
2415 first += 2;
2416 break;
2417 case 'O':
2418 db.names.push_back("operator^=");
2419 first += 2;
2420 break;
2421 case 'q':
2422 db.names.push_back("operator==");
2423 first += 2;
2424 break;
2425 }
2426 break;
2427 case 'g':
2428 switch (first[1])
2429 {
2430 case 'e':
2431 db.names.push_back("operator>=");
2432 first += 2;
2433 break;
2434 case 't':
2435 db.names.push_back("operator>");
2436 first += 2;
2437 break;
2438 }
2439 break;
2440 case 'i':
2441 if (first[1] == 'x')
2442 {
2443 db.names.push_back("operator[]");
2444 first += 2;
2445 }
2446 break;
2447 case 'l':
2448 switch (first[1])
2449 {
2450 case 'e':
2451 db.names.push_back("operator<=");
2452 first += 2;
2453 break;
Howard Hinnantf29757a2014-01-06 23:05:04 +00002454 case 'i':
2455 {
2456 const char* t = parse_source_name(first+2, last, db);
2457 if (t != first+2)
2458 {
2459 if (db.names.empty())
2460 return first;
2461 db.names.back().first.insert(0, "operator\"\" ");
2462 first = t;
2463 }
2464 }
2465 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002466 case 's':
2467 db.names.push_back("operator<<");
2468 first += 2;
2469 break;
2470 case 'S':
2471 db.names.push_back("operator<<=");
2472 first += 2;
2473 break;
2474 case 't':
2475 db.names.push_back("operator<");
2476 first += 2;
2477 break;
2478 }
2479 break;
2480 case 'm':
2481 switch (first[1])
2482 {
2483 case 'i':
2484 db.names.push_back("operator-");
2485 first += 2;
2486 break;
2487 case 'I':
2488 db.names.push_back("operator-=");
2489 first += 2;
2490 break;
2491 case 'l':
2492 db.names.push_back("operator*");
2493 first += 2;
2494 break;
2495 case 'L':
2496 db.names.push_back("operator*=");
2497 first += 2;
2498 break;
2499 case 'm':
2500 db.names.push_back("operator--");
2501 first += 2;
2502 break;
2503 }
2504 break;
2505 case 'n':
2506 switch (first[1])
2507 {
2508 case 'a':
2509 db.names.push_back("operator new[]");
2510 first += 2;
2511 break;
2512 case 'e':
2513 db.names.push_back("operator!=");
2514 first += 2;
2515 break;
2516 case 'g':
2517 db.names.push_back("operator-");
2518 first += 2;
2519 break;
2520 case 't':
2521 db.names.push_back("operator!");
2522 first += 2;
2523 break;
2524 case 'w':
2525 db.names.push_back("operator new");
2526 first += 2;
2527 break;
2528 }
2529 break;
2530 case 'o':
2531 switch (first[1])
2532 {
2533 case 'o':
2534 db.names.push_back("operator||");
2535 first += 2;
2536 break;
2537 case 'r':
2538 db.names.push_back("operator|");
2539 first += 2;
2540 break;
2541 case 'R':
2542 db.names.push_back("operator|=");
2543 first += 2;
2544 break;
2545 }
2546 break;
2547 case 'p':
2548 switch (first[1])
2549 {
2550 case 'm':
2551 db.names.push_back("operator->*");
2552 first += 2;
2553 break;
2554 case 'l':
2555 db.names.push_back("operator+");
2556 first += 2;
2557 break;
2558 case 'L':
2559 db.names.push_back("operator+=");
2560 first += 2;
2561 break;
2562 case 'p':
2563 db.names.push_back("operator++");
2564 first += 2;
2565 break;
2566 case 's':
2567 db.names.push_back("operator+");
2568 first += 2;
2569 break;
2570 case 't':
2571 db.names.push_back("operator->");
2572 first += 2;
2573 break;
2574 }
2575 break;
2576 case 'q':
2577 if (first[1] == 'u')
2578 {
2579 db.names.push_back("operator?");
2580 first += 2;
2581 }
2582 break;
2583 case 'r':
2584 switch (first[1])
2585 {
2586 case 'm':
2587 db.names.push_back("operator%");
2588 first += 2;
2589 break;
2590 case 'M':
2591 db.names.push_back("operator%=");
2592 first += 2;
2593 break;
2594 case 's':
2595 db.names.push_back("operator>>");
2596 first += 2;
2597 break;
2598 case 'S':
2599 db.names.push_back("operator>>=");
2600 first += 2;
2601 break;
2602 }
2603 break;
2604 case 'v':
2605 if (std::isdigit(first[1]))
2606 {
2607 const char* t = parse_source_name(first+2, last, db);
2608 if (t != first+2)
2609 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002610 if (db.names.empty())
2611 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002612 db.names.back().first.insert(0, "operator ");
2613 first = t;
2614 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002615 }
2616 break;
2617 }
2618 }
2619 return first;
2620}
2621
Howard Hinnant6c33e762013-06-17 18:10:34 +00002622template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00002623const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00002624parse_integer_literal(const char* first, const char* last, const typename C::String& lit, C& db)
2625{
2626 const char* t = parse_number(first, last);
2627 if (t != first && t != last && *t == 'E')
2628 {
2629 if (lit.size() > 3)
2630 db.names.push_back("(" + lit + ")");
2631 else
2632 db.names.emplace_back();
2633 if (*first == 'n')
2634 {
2635 db.names.back().first += '-';
2636 ++first;
2637 }
2638 db.names.back().first.append(first, t);
2639 if (lit.size() <= 3)
2640 db.names.back().first += lit;
2641 first = t+1;
2642 }
2643 return first;
2644}
2645
2646// <expr-primary> ::= L <type> <value number> E # integer literal
2647// ::= L <type> <value float> E # floating literal
2648// ::= L <string type> E # string literal
2649// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
2650// ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
2651// ::= L <mangled-name> E # external name
2652
2653template <class C>
2654const char*
2655parse_expr_primary(const char* first, const char* last, C& db)
2656{
2657 if (last - first >= 4 && *first == 'L')
2658 {
2659 switch (first[1])
2660 {
2661 case 'w':
Howard Hinnant93433df2013-06-20 21:49:34 +00002662 {
2663 const char* t = parse_integer_literal(first+2, last, "wchar_t", db);
2664 if (t != first+2)
2665 first = t;
2666 }
2667 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002668 case 'b':
2669 if (first[3] == 'E')
2670 {
2671 switch (first[2])
2672 {
2673 case '0':
2674 db.names.push_back("false");
2675 first += 4;
2676 break;
2677 case '1':
2678 db.names.push_back("true");
2679 first += 4;
2680 break;
2681 }
2682 }
2683 break;
2684 case 'c':
Howard Hinnant93433df2013-06-20 21:49:34 +00002685 {
2686 const char* t = parse_integer_literal(first+2, last, "char", db);
2687 if (t != first+2)
2688 first = t;
2689 }
2690 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002691 case 'a':
Howard Hinnant93433df2013-06-20 21:49:34 +00002692 {
2693 const char* t = parse_integer_literal(first+2, last, "signed char", db);
2694 if (t != first+2)
2695 first = t;
2696 }
2697 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002698 case 'h':
Howard Hinnant93433df2013-06-20 21:49:34 +00002699 {
2700 const char* t = parse_integer_literal(first+2, last, "unsigned char", db);
2701 if (t != first+2)
2702 first = t;
2703 }
2704 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002705 case 's':
Howard Hinnant93433df2013-06-20 21:49:34 +00002706 {
2707 const char* t = parse_integer_literal(first+2, last, "short", db);
2708 if (t != first+2)
2709 first = t;
2710 }
2711 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002712 case 't':
Howard Hinnant93433df2013-06-20 21:49:34 +00002713 {
2714 const char* t = parse_integer_literal(first+2, last, "unsigned short", db);
2715 if (t != first+2)
2716 first = t;
2717 }
2718 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002719 case 'i':
Howard Hinnant93433df2013-06-20 21:49:34 +00002720 {
2721 const char* t = parse_integer_literal(first+2, last, "", db);
2722 if (t != first+2)
2723 first = t;
2724 }
2725 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002726 case 'j':
Howard Hinnant93433df2013-06-20 21:49:34 +00002727 {
2728 const char* t = parse_integer_literal(first+2, last, "u", db);
2729 if (t != first+2)
2730 first = t;
2731 }
2732 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002733 case 'l':
Howard Hinnant93433df2013-06-20 21:49:34 +00002734 {
2735 const char* t = parse_integer_literal(first+2, last, "l", db);
2736 if (t != first+2)
2737 first = t;
2738 }
2739 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002740 case 'm':
Howard Hinnant93433df2013-06-20 21:49:34 +00002741 {
2742 const char* t = parse_integer_literal(first+2, last, "ul", db);
2743 if (t != first+2)
2744 first = t;
2745 }
2746 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002747 case 'x':
Howard Hinnant93433df2013-06-20 21:49:34 +00002748 {
2749 const char* t = parse_integer_literal(first+2, last, "ll", db);
2750 if (t != first+2)
2751 first = t;
2752 }
2753 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002754 case 'y':
Howard Hinnant93433df2013-06-20 21:49:34 +00002755 {
2756 const char* t = parse_integer_literal(first+2, last, "ull", db);
2757 if (t != first+2)
2758 first = t;
2759 }
2760 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002761 case 'n':
Howard Hinnant93433df2013-06-20 21:49:34 +00002762 {
2763 const char* t = parse_integer_literal(first+2, last, "__int128", db);
2764 if (t != first+2)
2765 first = t;
2766 }
2767 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002768 case 'o':
Howard Hinnant93433df2013-06-20 21:49:34 +00002769 {
2770 const char* t = parse_integer_literal(first+2, last, "unsigned __int128", db);
2771 if (t != first+2)
2772 first = t;
2773 }
2774 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002775 case 'f':
Howard Hinnant93433df2013-06-20 21:49:34 +00002776 {
2777 const char* t = parse_floating_number<float>(first+2, last, db);
2778 if (t != first+2)
2779 first = t;
2780 }
2781 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002782 case 'd':
Howard Hinnant93433df2013-06-20 21:49:34 +00002783 {
2784 const char* t = parse_floating_number<double>(first+2, last, db);
2785 if (t != first+2)
2786 first = t;
2787 }
2788 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002789 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00002790 {
2791 const char* t = parse_floating_number<long double>(first+2, last, db);
2792 if (t != first+2)
2793 first = t;
2794 }
2795 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002796 case '_':
2797 if (first[2] == 'Z')
2798 {
2799 const char* t = parse_encoding(first+3, last, db);
2800 if (t != first+3 && t != last && *t == 'E')
2801 first = t+1;
2802 }
2803 break;
2804 case 'T':
2805 // Invalid mangled name per
2806 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
2807 break;
2808 default:
2809 {
2810 // might be named type
2811 const char* t = parse_type(first+1, last, db);
2812 if (t != first+1 && t != last)
2813 {
2814 if (*t != 'E')
2815 {
2816 const char* n = t;
2817 for (; n != last && isdigit(*n); ++n)
2818 ;
2819 if (n != t && n != last && *n == 'E')
2820 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00002821 if (db.names.empty())
2822 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002823 db.names.back() = "(" + db.names.back().move_full() + ")" + typename C::String(t, n);
2824 first = n+1;
2825 break;
2826 }
2827 }
2828 else
2829 {
2830 first = t+1;
2831 break;
2832 }
2833 }
2834 }
2835 }
2836 }
2837 return first;
2838}
2839
2840template <class String>
2841String
2842base_name(String& s)
2843{
2844 if (s.empty())
2845 return s;
2846 if (s == "std::string")
2847 {
2848 s = "std::basic_string<char, std::char_traits<char>, std::allocator<char> >";
2849 return "basic_string";
2850 }
2851 if (s == "std::istream")
2852 {
2853 s = "std::basic_istream<char, std::char_traits<char> >";
2854 return "basic_istream";
2855 }
2856 if (s == "std::ostream")
2857 {
2858 s = "std::basic_ostream<char, std::char_traits<char> >";
2859 return "basic_ostream";
2860 }
2861 if (s == "std::iostream")
2862 {
2863 s = "std::basic_iostream<char, std::char_traits<char> >";
2864 return "basic_iostream";
2865 }
2866 const char* const pf = s.data();
2867 const char* pe = pf + s.size();
2868 if (pe[-1] == '>')
2869 {
2870 unsigned c = 1;
2871 while (true)
2872 {
2873 if (--pe == pf)
2874 return String();
2875 if (pe[-1] == '<')
2876 {
2877 if (--c == 0)
2878 {
2879 --pe;
2880 break;
2881 }
2882 }
2883 else if (pe[-1] == '>')
2884 ++c;
2885 }
2886 }
2887 const char* p0 = pe - 1;
2888 for (; p0 != pf; --p0)
2889 {
2890 if (*p0 == ':')
2891 {
2892 ++p0;
2893 break;
2894 }
2895 }
2896 return String(p0, pe);
2897}
2898
2899// <ctor-dtor-name> ::= C1 # complete object constructor
2900// ::= C2 # base object constructor
2901// ::= C3 # complete object allocating constructor
2902// extension ::= C5 # ?
2903// ::= D0 # deleting destructor
2904// ::= D1 # complete object destructor
2905// ::= D2 # base object destructor
2906// extension ::= D5 # ?
2907
2908template <class C>
2909const char*
2910parse_ctor_dtor_name(const char* first, const char* last, C& db)
2911{
2912 if (last-first >= 2 && !db.names.empty())
2913 {
2914 switch (first[0])
2915 {
2916 case 'C':
2917 switch (first[1])
2918 {
2919 case '1':
2920 case '2':
2921 case '3':
2922 case '5':
Howard Hinnant753a30d2013-12-11 19:44:25 +00002923 if (db.names.empty())
2924 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002925 db.names.push_back(base_name(db.names.back().first));
2926 first += 2;
2927 db.parsed_ctor_dtor_cv = true;
2928 break;
2929 }
2930 break;
2931 case 'D':
2932 switch (first[1])
2933 {
2934 case '0':
2935 case '1':
2936 case '2':
2937 case '5':
Howard Hinnant753a30d2013-12-11 19:44:25 +00002938 if (db.names.empty())
2939 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00002940 db.names.push_back("~" + base_name(db.names.back().first));
2941 first += 2;
2942 db.parsed_ctor_dtor_cv = true;
2943 break;
2944 }
2945 break;
2946 }
2947 }
2948 return first;
2949}
2950
2951// <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
2952// ::= <closure-type-name>
2953//
2954// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2955//
2956// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
2957
2958template <class C>
2959const char*
2960parse_unnamed_type_name(const char* first, const char* last, C& db)
2961{
2962 if (last - first > 2 && first[0] == 'U')
2963 {
2964 char type = first[1];
2965 switch (type)
2966 {
2967 case 't':
2968 {
2969 db.names.push_back(typename C::String("'unnamed"));
2970 const char* t0 = first+2;
2971 if (t0 == last)
2972 {
2973 db.names.pop_back();
2974 return first;
2975 }
2976 if (std::isdigit(*t0))
2977 {
2978 const char* t1 = t0 + 1;
2979 while (t1 != last && std::isdigit(*t1))
2980 ++t1;
2981 db.names.back().first.append(t0, t1);
2982 t0 = t1;
2983 }
2984 db.names.back().first.push_back('\'');
2985 if (t0 == last || *t0 != '_')
2986 {
2987 db.names.pop_back();
2988 return first;
2989 }
2990 first = t0 + 1;
2991 }
2992 break;
2993 case 'l':
2994 {
2995 db.names.push_back(typename C::String("'lambda'("));
2996 const char* t0 = first+2;
2997 if (first[2] == 'v')
2998 {
2999 db.names.back().first += ')';
3000 ++t0;
3001 }
3002 else
3003 {
3004 const char* t1 = parse_type(t0, last, db);
3005 if (t1 == t0)
3006 {
3007 db.names.pop_back();
3008 return first;
3009 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00003010 if (db.names.size() < 2)
3011 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003012 auto tmp = db.names.back().move_full();
3013 db.names.pop_back();
3014 db.names.back().first.append(tmp);
3015 t0 = t1;
3016 while (true)
3017 {
3018 t1 = parse_type(t0, last, db);
3019 if (t1 == t0)
3020 break;
Howard Hinnant753a30d2013-12-11 19:44:25 +00003021 if (db.names.size() < 2)
3022 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003023 tmp = db.names.back().move_full();
3024 db.names.pop_back();
3025 if (!tmp.empty())
3026 {
3027 db.names.back().first.append(", ");
3028 db.names.back().first.append(tmp);
3029 }
3030 t0 = t1;
3031 }
3032 db.names.back().first.append(")");
3033 }
3034 if (t0 == last || *t0 != 'E')
3035 {
3036 db.names.pop_back();
3037 return first;
3038 }
3039 ++t0;
3040 if (t0 == last)
3041 {
3042 db.names.pop_back();
3043 return first;
3044 }
3045 if (std::isdigit(*t0))
3046 {
3047 const char* t1 = t0 + 1;
3048 while (t1 != last && std::isdigit(*t1))
3049 ++t1;
3050 db.names.back().first.insert(db.names.back().first.begin()+7, t0, t1);
3051 t0 = t1;
3052 }
3053 if (t0 == last || *t0 != '_')
3054 {
3055 db.names.pop_back();
3056 return first;
3057 }
3058 first = t0 + 1;
3059 }
3060 break;
3061 }
3062 }
3063 return first;
3064}
3065
3066// <unqualified-name> ::= <operator-name>
3067// ::= <ctor-dtor-name>
3068// ::= <source-name>
3069// ::= <unnamed-type-name>
3070
3071template <class C>
3072const char*
3073parse_unqualified_name(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003074{
3075 if (first != last)
3076 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00003077 const char* t;
3078 switch (*first)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003079 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00003080 case 'C':
3081 case 'D':
3082 t = parse_ctor_dtor_name(first, last, db);
3083 if (t != first)
3084 first = t;
3085 break;
3086 case 'U':
3087 t = parse_unnamed_type_name(first, last, db);
3088 if (t != first)
3089 first = t;
3090 break;
3091 case '1':
3092 case '2':
3093 case '3':
3094 case '4':
3095 case '5':
3096 case '6':
3097 case '7':
3098 case '8':
3099 case '9':
3100 t = parse_source_name(first, last, db);
3101 if (t != first)
3102 first = t;
3103 break;
3104 default:
3105 t = parse_operator_name(first, last, db);
3106 if (t != first)
3107 first = t;
3108 break;
3109 };
3110 }
3111 return first;
3112}
3113
3114// <unscoped-name> ::= <unqualified-name>
3115// ::= St <unqualified-name> # ::std::
3116// extension ::= StL<unqualified-name>
3117
3118template <class C>
3119const char*
3120parse_unscoped_name(const char* first, const char* last, C& db)
3121{
3122 if (last - first >= 2)
3123 {
3124 const char* t0 = first;
3125 bool St = false;
3126 if (first[0] == 'S' && first[1] == 't')
3127 {
3128 t0 += 2;
3129 St = true;
3130 if (t0 != last && *t0 == 'L')
3131 ++t0;
3132 }
3133 const char* t1 = parse_unqualified_name(t0, last, db);
3134 if (t1 != t0)
3135 {
3136 if (St)
Howard Hinnant753a30d2013-12-11 19:44:25 +00003137 {
3138 if (db.names.empty())
3139 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003140 db.names.back().first.insert(0, "std::");
Howard Hinnant753a30d2013-12-11 19:44:25 +00003141 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003142 first = t1;
3143 }
3144 }
3145 return first;
3146}
3147
3148// at <type> # alignof (a type)
3149
3150template <class C>
3151const char*
3152parse_alignof_type(const char* first, const char* last, C& db)
3153{
3154 if (last - first >= 3 && first[0] == 'a' && first[1] == 't')
3155 {
3156 const char* t = parse_type(first+2, last, db);
3157 if (t != first+2)
3158 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003159 if (db.names.empty())
3160 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003161 db.names.back().first = "alignof (" + db.names.back().move_full() + ")";
3162 first = t;
3163 }
3164 }
3165 return first;
3166}
3167
3168// az <expression> # alignof (a expression)
3169
3170template <class C>
3171const char*
3172parse_alignof_expr(const char* first, const char* last, C& db)
3173{
3174 if (last - first >= 3 && first[0] == 'a' && first[1] == 'z')
3175 {
3176 const char* t = parse_expression(first+2, last, db);
3177 if (t != first+2)
3178 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003179 if (db.names.empty())
3180 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003181 db.names.back().first = "alignof (" + db.names.back().move_full() + ")";
3182 first = t;
3183 }
3184 }
3185 return first;
3186}
3187
3188template <class C>
3189const char*
3190parse_noexcept_expression(const char* first, const char* last, C& db)
3191{
3192 const char* t1 = parse_expression(first, last, db);
3193 if (t1 != first)
3194 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003195 if (db.names.empty())
3196 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003197 db.names.back().first = "noexcept (" + db.names.back().move_full() + ")";
3198 first = t1;
3199 }
3200 return first;
3201}
3202
3203template <class C>
3204const char*
3205parse_prefix_expression(const char* first, const char* last, const typename C::String& op, C& db)
3206{
3207 const char* t1 = parse_expression(first, last, db);
3208 if (t1 != first)
3209 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003210 if (db.names.empty())
3211 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003212 db.names.back().first = op + "(" + db.names.back().move_full() + ")";
3213 first = t1;
3214 }
3215 return first;
3216}
3217
3218template <class C>
3219const char*
3220parse_binary_expression(const char* first, const char* last, const typename C::String& op, C& db)
3221{
3222 const char* t1 = parse_expression(first, last, db);
3223 if (t1 != first)
3224 {
3225 const char* t2 = parse_expression(t1, last, db);
3226 if (t2 != t1)
3227 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003228 if (db.names.size() < 2)
3229 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003230 auto op2 = db.names.back().move_full();
3231 db.names.pop_back();
3232 auto op1 = db.names.back().move_full();
3233 auto& nm = db.names.back().first;
3234 nm.clear();
3235 if (op == ">")
3236 nm += '(';
3237 nm += "(" + op1 + ") " + op + " (" + op2 + ")";
3238 if (op == ">")
3239 nm += ')';
3240 first = t2;
3241 }
3242 else
3243 db.names.pop_back();
3244 }
3245 return first;
3246}
3247
3248// <expression> ::= <unary operator-name> <expression>
3249// ::= <binary operator-name> <expression> <expression>
3250// ::= <ternary operator-name> <expression> <expression> <expression>
3251// ::= cl <expression>+ E # call
3252// ::= cv <type> <expression> # conversion with one argument
3253// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
3254// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
3255// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
3256// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
3257// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
3258// ::= [gs] dl <expression> # delete expression
3259// ::= [gs] da <expression> # delete[] expression
3260// ::= pp_ <expression> # prefix ++
3261// ::= mm_ <expression> # prefix --
3262// ::= ti <type> # typeid (type)
3263// ::= te <expression> # typeid (expression)
3264// ::= dc <type> <expression> # dynamic_cast<type> (expression)
3265// ::= sc <type> <expression> # static_cast<type> (expression)
3266// ::= cc <type> <expression> # const_cast<type> (expression)
3267// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
3268// ::= st <type> # sizeof (a type)
3269// ::= sz <expression> # sizeof (an expression)
3270// ::= at <type> # alignof (a type)
3271// ::= az <expression> # alignof (an expression)
3272// ::= nx <expression> # noexcept (expression)
3273// ::= <template-param>
3274// ::= <function-param>
3275// ::= dt <expression> <unresolved-name> # expr.name
3276// ::= pt <expression> <unresolved-name> # expr->name
3277// ::= ds <expression> <expression> # expr.*expr
3278// ::= sZ <template-param> # size of a parameter pack
3279// ::= sZ <function-param> # size of a function parameter pack
3280// ::= sp <expression> # pack expansion
3281// ::= tw <expression> # throw expression
3282// ::= tr # throw with no operand (rethrow)
3283// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
3284// # freestanding dependent name (e.g., T::x),
3285// # objectless nonstatic member reference
3286// ::= <expr-primary>
3287
3288template <class C>
3289const char*
3290parse_expression(const char* first, const char* last, C& db)
3291{
3292 if (last - first >= 2)
3293 {
3294 const char* t = first;
3295 bool parsed_gs = false;
3296 if (last - first >= 4 && t[0] == 'g' && t[1] == 's')
3297 {
3298 t += 2;
3299 parsed_gs = true;
3300 }
3301 switch (*t)
3302 {
3303 case 'L':
3304 first = parse_expr_primary(first, last, db);
3305 break;
3306 case 'T':
3307 first = parse_template_param(first, last, db);
3308 break;
3309 case 'f':
3310 first = parse_function_param(first, last, db);
3311 break;
3312 case 'a':
3313 switch (t[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003314 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00003315 case 'a':
Howard Hinnant93433df2013-06-20 21:49:34 +00003316 t = parse_binary_expression(first+2, last, "&&", db);
3317 if (t != first+2)
3318 first = t;
3319 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003320 case 'd':
Howard Hinnant93433df2013-06-20 21:49:34 +00003321 t = parse_prefix_expression(first+2, last, "&", db);
3322 if (t != first+2)
3323 first = t;
3324 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003325 case 'n':
Howard Hinnant93433df2013-06-20 21:49:34 +00003326 t = parse_binary_expression(first+2, last, "&", db);
3327 if (t != first+2)
3328 first = t;
3329 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003330 case 'N':
Howard Hinnant93433df2013-06-20 21:49:34 +00003331 t = parse_binary_expression(first+2, last, "&=", db);
3332 if (t != first+2)
3333 first = t;
3334 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003335 case 'S':
Howard Hinnant93433df2013-06-20 21:49:34 +00003336 t = parse_binary_expression(first+2, last, "=", db);
3337 if (t != first+2)
3338 first = t;
3339 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003340 case 't':
3341 first = parse_alignof_type(first, last, db);
3342 break;
3343 case 'z':
3344 first = parse_alignof_expr(first, last, db);
3345 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003346 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003347 break;
3348 case 'c':
3349 switch (t[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003350 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00003351 case 'c':
3352 first = parse_const_cast_expr(first, last, db);
3353 break;
3354 case 'l':
3355 first = parse_call_expr(first, last, db);
3356 break;
3357 case 'm':
Howard Hinnant93433df2013-06-20 21:49:34 +00003358 t = parse_binary_expression(first+2, last, ",", db);
3359 if (t != first+2)
3360 first = t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003361 break;
3362 case 'o':
Howard Hinnant93433df2013-06-20 21:49:34 +00003363 t = parse_prefix_expression(first+2, last, "~", db);
3364 if (t != first+2)
3365 first = t;
3366 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003367 case 'v':
3368 first = parse_conversion_expr(first, last, db);
3369 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00003370 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003371 break;
3372 case 'd':
3373 switch (t[1])
3374 {
3375 case 'a':
3376 {
3377 const char* t1 = parse_expression(t+2, last, db);
3378 if (t1 != t+2)
3379 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003380 if (db.names.empty())
3381 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003382 db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) +
3383 "delete[] " + db.names.back().move_full();
3384 first = t1;
3385 }
3386 }
3387 break;
3388 case 'c':
3389 first = parse_dynamic_cast_expr(first, last, db);
3390 break;
3391 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00003392 t = parse_prefix_expression(first+2, last, "*", db);
3393 if (t != first+2)
3394 first = t;
3395 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003396 case 'l':
3397 {
3398 const char* t1 = parse_expression(t+2, last, db);
3399 if (t1 != t+2)
3400 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003401 if (db.names.empty())
3402 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003403 db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) +
3404 "delete " + db.names.back().move_full();
3405 first = t1;
3406 }
3407 }
3408 break;
3409 case 'n':
3410 return parse_unresolved_name(first, last, db);
3411 case 's':
3412 first = parse_dot_star_expr(first, last, db);
3413 break;
3414 case 't':
3415 first = parse_dot_expr(first, last, db);
3416 break;
3417 case 'v':
Howard Hinnant93433df2013-06-20 21:49:34 +00003418 t = parse_binary_expression(first+2, last, "/", db);
3419 if (t != first+2)
3420 first = t;
3421 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003422 case 'V':
Howard Hinnant93433df2013-06-20 21:49:34 +00003423 t = parse_binary_expression(first+2, last, "/=", db);
3424 if (t != first+2)
3425 first = t;
3426 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003427 }
3428 break;
3429 case 'e':
3430 switch (t[1])
3431 {
3432 case 'o':
Howard Hinnant93433df2013-06-20 21:49:34 +00003433 t = parse_binary_expression(first+2, last, "^", db);
3434 if (t != first+2)
3435 first = t;
3436 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003437 case 'O':
Howard Hinnant93433df2013-06-20 21:49:34 +00003438 t = parse_binary_expression(first+2, last, "^=", db);
3439 if (t != first+2)
3440 first = t;
3441 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003442 case 'q':
Howard Hinnant93433df2013-06-20 21:49:34 +00003443 t = parse_binary_expression(first+2, last, "==", db);
3444 if (t != first+2)
3445 first = t;
3446 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003447 }
3448 break;
3449 case 'g':
3450 switch (t[1])
3451 {
3452 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00003453 t = parse_binary_expression(first+2, last, ">=", db);
3454 if (t != first+2)
3455 first = t;
3456 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003457 case 't':
Howard Hinnant93433df2013-06-20 21:49:34 +00003458 t = parse_binary_expression(first+2, last, ">", db);
3459 if (t != first+2)
3460 first = t;
3461 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003462 }
3463 break;
3464 case 'i':
3465 if (t[1] == 'x')
3466 {
3467 const char* t1 = parse_expression(first+2, last, db);
3468 if (t1 != first+2)
3469 {
3470 const char* t2 = parse_expression(t1, last, db);
3471 if (t2 != t1)
3472 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003473 if (db.names.size() < 2)
3474 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003475 auto op2 = db.names.back().move_full();
3476 db.names.pop_back();
3477 auto op1 = db.names.back().move_full();
3478 db.names.back() = "(" + op1 + ")[" + op2 + "]";
3479 first = t2;
3480 }
3481 else
3482 db.names.pop_back();
3483 }
3484 }
3485 break;
3486 case 'l':
3487 switch (t[1])
3488 {
3489 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00003490 t = parse_binary_expression(first+2, last, "<=", db);
3491 if (t != first+2)
3492 first = t;
3493 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003494 case 's':
Howard Hinnant93433df2013-06-20 21:49:34 +00003495 t = parse_binary_expression(first+2, last, "<<", db);
3496 if (t != first+2)
3497 first = t;
3498 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003499 case 'S':
Howard Hinnant93433df2013-06-20 21:49:34 +00003500 t = parse_binary_expression(first+2, last, "<<=", db);
3501 if (t != first+2)
3502 first = t;
3503 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003504 case 't':
Howard Hinnant93433df2013-06-20 21:49:34 +00003505 t = parse_binary_expression(first+2, last, "<", db);
3506 if (t != first+2)
3507 first = t;
3508 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003509 }
3510 break;
3511 case 'm':
3512 switch (t[1])
3513 {
3514 case 'i':
Howard Hinnant93433df2013-06-20 21:49:34 +00003515 t = parse_binary_expression(first+2, last, "-", db);
3516 if (t != first+2)
3517 first = t;
3518 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003519 case 'I':
Howard Hinnant93433df2013-06-20 21:49:34 +00003520 t = parse_binary_expression(first+2, last, "-=", db);
3521 if (t != first+2)
3522 first = t;
3523 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003524 case 'l':
Howard Hinnant93433df2013-06-20 21:49:34 +00003525 t = parse_binary_expression(first+2, last, "*", db);
3526 if (t != first+2)
3527 first = t;
3528 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003529 case 'L':
Howard Hinnant93433df2013-06-20 21:49:34 +00003530 t = parse_binary_expression(first+2, last, "*=", db);
3531 if (t != first+2)
3532 first = t;
3533 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003534 case 'm':
3535 if (first+2 != last && first[2] == '_')
Howard Hinnant93433df2013-06-20 21:49:34 +00003536 {
3537 t = parse_prefix_expression(first+3, last, "--", db);
3538 if (t != first+3)
3539 first = t;
3540 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003541 else
3542 {
3543 const char* t1 = parse_expression(first+2, last, db);
3544 if (t1 != first+2)
3545 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003546 if (db.names.empty())
3547 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003548 db.names.back() = "(" + db.names.back().move_full() + ")--";
3549 first = t1;
3550 }
3551 }
3552 break;
3553 }
3554 break;
3555 case 'n':
3556 switch (t[1])
3557 {
3558 case 'a':
3559 case 'w':
3560 first = parse_new_expr(first, last, db);
3561 break;
3562 case 'e':
Howard Hinnant93433df2013-06-20 21:49:34 +00003563 t = parse_binary_expression(first+2, last, "!=", db);
3564 if (t != first+2)
3565 first = t;
3566 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003567 case 'g':
Howard Hinnant93433df2013-06-20 21:49:34 +00003568 t = parse_prefix_expression(first+2, last, "-", db);
3569 if (t != first+2)
3570 first = t;
3571 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003572 case 't':
Howard Hinnant93433df2013-06-20 21:49:34 +00003573 t = parse_prefix_expression(first+2, last, "!", db);
3574 if (t != first+2)
3575 first = t;
3576 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003577 case 'x':
Howard Hinnant93433df2013-06-20 21:49:34 +00003578 t = parse_noexcept_expression(first+2, last, db);
3579 if (t != first+2)
3580 first = t;
3581 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003582 }
3583 break;
3584 case 'o':
3585 switch (t[1])
3586 {
3587 case 'n':
3588 return parse_unresolved_name(first, last, db);
3589 case 'o':
Howard Hinnant93433df2013-06-20 21:49:34 +00003590 t = parse_binary_expression(first+2, last, "||", db);
3591 if (t != first+2)
3592 first = t;
3593 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003594 case 'r':
Howard Hinnant93433df2013-06-20 21:49:34 +00003595 t = parse_binary_expression(first+2, last, "|", db);
3596 if (t != first+2)
3597 first = t;
3598 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003599 case 'R':
Howard Hinnant93433df2013-06-20 21:49:34 +00003600 t = parse_binary_expression(first+2, last, "|=", db);
3601 if (t != first+2)
3602 first = t;
3603 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003604 }
3605 break;
3606 case 'p':
3607 switch (t[1])
3608 {
3609 case 'm':
Howard Hinnant93433df2013-06-20 21:49:34 +00003610 t = parse_binary_expression(first+2, last, "->*", db);
3611 if (t != first+2)
3612 first = t;
3613 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003614 case 'l':
Howard Hinnant93433df2013-06-20 21:49:34 +00003615 t = parse_binary_expression(first+2, last, "+", db);
3616 if (t != first+2)
3617 first = t;
3618 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003619 case 'L':
Howard Hinnant93433df2013-06-20 21:49:34 +00003620 t = parse_binary_expression(first+2, last, "+=", db);
3621 if (t != first+2)
3622 first = t;
3623 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003624 case 'p':
3625 if (first+2 != last && first[2] == '_')
Howard Hinnant93433df2013-06-20 21:49:34 +00003626 {
3627 t = parse_prefix_expression(first+3, last, "++", db);
3628 if (t != first+3)
3629 first = t;
3630 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00003631 else
3632 {
3633 const char* t1 = parse_expression(first+2, last, db);
3634 if (t1 != first+2)
3635 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003636 if (db.names.empty())
3637 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003638 db.names.back() = "(" + db.names.back().move_full() + ")++";
3639 first = t1;
3640 }
3641 }
3642 break;
3643 case 's':
Howard Hinnant93433df2013-06-20 21:49:34 +00003644 t = parse_prefix_expression(first+2, last, "+", db);
3645 if (t != first+2)
3646 first = t;
3647 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003648 case 't':
3649 first = parse_arrow_expr(first, last, db);
3650 break;
3651 }
3652 break;
3653 case 'q':
3654 if (t[1] == 'u')
3655 {
3656 const char* t1 = parse_expression(first+2, last, db);
3657 if (t1 != first+2)
3658 {
3659 const char* t2 = parse_expression(t1, last, db);
3660 if (t2 != t1)
3661 {
3662 const char* t3 = parse_expression(t2, last, db);
3663 if (t3 != t2)
3664 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00003665 if (db.names.size() < 3)
3666 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003667 auto op3 = db.names.back().move_full();
3668 db.names.pop_back();
3669 auto op2 = db.names.back().move_full();
3670 db.names.pop_back();
3671 auto op1 = db.names.back().move_full();
3672 db.names.back() = "(" + op1 + ") ? (" + op2 + ") : (" + op3 + ")";
3673 first = t3;
3674 }
3675 else
3676 {
3677 db.names.pop_back();
3678 db.names.pop_back();
3679 }
3680 }
3681 else
3682 db.names.pop_back();
3683 }
3684 }
3685 break;
3686 case 'r':
3687 switch (t[1])
3688 {
3689 case 'c':
3690 first = parse_reinterpret_cast_expr(first, last, db);
3691 break;
3692 case 'm':
Howard Hinnant93433df2013-06-20 21:49:34 +00003693 t = parse_binary_expression(first+2, last, "%", db);
3694 if (t != first+2)
3695 first = t;
3696 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003697 case 'M':
Howard Hinnant93433df2013-06-20 21:49:34 +00003698 t = parse_binary_expression(first+2, last, "%=", db);
3699 if (t != first+2)
3700 first = t;
3701 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003702 case 's':
Howard Hinnant93433df2013-06-20 21:49:34 +00003703 t = parse_binary_expression(first+2, last, ">>", db);
3704 if (t != first+2)
3705 first = t;
3706 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003707 case 'S':
Howard Hinnant93433df2013-06-20 21:49:34 +00003708 t = parse_binary_expression(first+2, last, ">>=", db);
3709 if (t != first+2)
3710 first = t;
3711 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003712 }
3713 break;
3714 case 's':
3715 switch (t[1])
3716 {
3717 case 'c':
3718 first = parse_static_cast_expr(first, last, db);
3719 break;
3720 case 'p':
3721 first = parse_pack_expansion(first, last, db);
3722 break;
3723 case 'r':
3724 return parse_unresolved_name(first, last, db);
3725 case 't':
3726 first = parse_sizeof_type_expr(first, last, db);
3727 break;
3728 case 'z':
3729 first = parse_sizeof_expr_expr(first, last, db);
3730 break;
3731 case 'Z':
3732 if (last - t >= 3)
3733 {
3734 switch (t[2])
3735 {
3736 case 'T':
3737 first = parse_sizeof_param_pack_expr(first, last, db);
3738 break;
3739 case 'f':
3740 first = parse_sizeof_function_param_pack_expr(first, last, db);
3741 break;
3742 }
3743 }
3744 break;
3745 }
3746 break;
3747 case 't':
3748 switch (t[1])
3749 {
3750 case 'e':
3751 case 'i':
3752 first = parse_typeid_expr(first, last, db);
3753 break;
3754 case 'r':
3755 db.names.push_back("throw");
3756 first += 2;
3757 break;
3758 case 'w':
3759 first = parse_throw_expr(first, last, db);
3760 break;
3761 }
3762 break;
3763 case '1':
3764 case '2':
3765 case '3':
3766 case '4':
3767 case '5':
3768 case '6':
3769 case '7':
3770 case '8':
3771 case '9':
3772 return parse_unresolved_name(first, last, db);
3773 }
3774 }
3775 return first;
3776}
3777
3778// <template-arg> ::= <type> # type or template
3779// ::= X <expression> E # expression
3780// ::= <expr-primary> # simple expressions
3781// ::= J <template-arg>* E # argument pack
3782// ::= LZ <encoding> E # extension
3783
3784template <class C>
3785const char*
3786parse_template_arg(const char* first, const char* last, C& db)
3787{
3788 if (first != last)
3789 {
3790 const char* t;
3791 switch (*first)
3792 {
3793 case 'X':
3794 t = parse_expression(first+1, last, db);
3795 if (t != first+1)
3796 {
3797 if (t != last && *t == 'E')
3798 first = t+1;
3799 }
3800 break;
3801 case 'J':
3802 t = first+1;
3803 if (t == last)
3804 return first;
3805 while (*t != 'E')
3806 {
3807 const char* t1 = parse_template_arg(t, last, db);
3808 if (t1 == t)
3809 return first;
3810 t = t1;
3811 }
3812 first = t+1;
3813 break;
3814 case 'L':
3815 // <expr-primary> or LZ <encoding> E
3816 if (first+1 != last && first[1] == 'Z')
3817 {
3818 t = parse_encoding(first+2, last, db);
3819 if (t != first+2 && t != last && *t == 'E')
3820 first = t+1;
3821 }
3822 else
3823 first = parse_expr_primary(first, last, db);
3824 break;
3825 default:
3826 // <type>
3827 first = parse_type(first, last, db);
3828 break;
3829 }
3830 }
3831 return first;
3832}
3833
3834// <template-args> ::= I <template-arg>* E
3835// extension, the abi says <template-arg>+
3836
3837template <class C>
3838const char*
3839parse_template_args(const char* first, const char* last, C& db)
3840{
3841 if (last - first >= 2 && *first == 'I')
3842 {
3843 if (db.tag_templates)
3844 db.template_param.back().clear();
3845 const char* t = first+1;
3846 typename C::String args("<");
3847 while (*t != 'E')
3848 {
3849 if (db.tag_templates)
3850 db.template_param.emplace_back(db.names.get_allocator());
3851 size_t k0 = db.names.size();
3852 const char* t1 = parse_template_arg(t, last, db);
3853 size_t k1 = db.names.size();
3854 if (db.tag_templates)
3855 db.template_param.pop_back();
3856 if (t1 == t || t1 == last)
3857 return first;
3858 if (db.tag_templates)
3859 {
3860 db.template_param.back().emplace_back(db.names.get_allocator());
3861 for (size_t k = k0; k < k1; ++k)
3862 db.template_param.back().back().push_back(db.names[k]);
3863 }
3864 for (size_t k = k0; k < k1; ++k)
3865 {
3866 if (args.size() > 1)
3867 args += ", ";
3868 args += db.names[k].move_full();
3869 }
3870 for (; k1 != k0; --k1)
3871 db.names.pop_back();
3872 t = t1;
3873 }
3874 first = t + 1;
3875 if (args.back() != '>')
3876 args += ">";
3877 else
3878 args += " >";
3879 db.names.push_back(std::move(args));
3880
3881 }
3882 return first;
3883}
3884
3885// <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
3886// ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
3887//
3888// <prefix> ::= <prefix> <unqualified-name>
3889// ::= <template-prefix> <template-args>
3890// ::= <template-param>
3891// ::= <decltype>
3892// ::= # empty
3893// ::= <substitution>
3894// ::= <prefix> <data-member-prefix>
3895// extension ::= L
3896//
3897// <template-prefix> ::= <prefix> <template unqualified-name>
3898// ::= <template-param>
3899// ::= <substitution>
3900
3901template <class C>
3902const char*
Richard Smith24ecd092014-05-12 18:44:13 +00003903parse_nested_name(const char* first, const char* last, C& db,
3904 bool* ends_with_template_args)
Howard Hinnant6c33e762013-06-17 18:10:34 +00003905{
3906 if (first != last && *first == 'N')
3907 {
3908 unsigned cv;
3909 const char* t0 = parse_cv_qualifiers(first+1, last, cv);
3910 if (t0 == last)
3911 return first;
3912 db.ref = 0;
3913 if (*t0 == 'R')
3914 {
3915 db.ref = 1;
3916 ++t0;
3917 }
3918 else if (*t0 == 'O')
3919 {
3920 db.ref = 2;
3921 ++t0;
3922 }
3923 db.names.emplace_back();
3924 if (last - t0 >= 2 && t0[0] == 'S' && t0[1] == 't')
3925 {
3926 t0 += 2;
3927 db.names.back().first = "std";
3928 }
3929 if (t0 == last)
3930 {
3931 db.names.pop_back();
3932 return first;
3933 }
3934 bool pop_subs = false;
Richard Smith24ecd092014-05-12 18:44:13 +00003935 bool component_ends_with_template_args = false;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003936 while (*t0 != 'E')
3937 {
Richard Smith24ecd092014-05-12 18:44:13 +00003938 component_ends_with_template_args = false;
Howard Hinnant6c33e762013-06-17 18:10:34 +00003939 const char* t1;
3940 switch (*t0)
3941 {
3942 case 'S':
3943 if (t0 + 1 != last && t0[1] == 't')
3944 goto do_parse_unqualified_name;
3945 t1 = parse_substitution(t0, last, db);
3946 if (t1 != t0 && t1 != last)
3947 {
3948 auto name = db.names.back().move_full();
3949 db.names.pop_back();
3950 if (!db.names.back().first.empty())
3951 {
3952 db.names.back().first += "::" + name;
3953 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
3954 }
3955 else
3956 db.names.back().first = name;
3957 pop_subs = true;
3958 t0 = t1;
3959 }
3960 else
3961 return first;
3962 break;
3963 case 'T':
3964 t1 = parse_template_param(t0, last, db);
3965 if (t1 != t0 && t1 != last)
3966 {
3967 auto name = db.names.back().move_full();
3968 db.names.pop_back();
3969 if (!db.names.back().first.empty())
3970 db.names.back().first += "::" + name;
3971 else
3972 db.names.back().first = name;
3973 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
3974 pop_subs = true;
3975 t0 = t1;
3976 }
3977 else
3978 return first;
3979 break;
3980 case 'D':
3981 if (t0 + 1 != last && t0[1] != 't' && t0[1] != 'T')
3982 goto do_parse_unqualified_name;
3983 t1 = parse_decltype(t0, last, db);
3984 if (t1 != t0 && t1 != last)
3985 {
3986 auto name = db.names.back().move_full();
3987 db.names.pop_back();
3988 if (!db.names.back().first.empty())
3989 db.names.back().first += "::" + name;
3990 else
3991 db.names.back().first = name;
3992 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
3993 pop_subs = true;
3994 t0 = t1;
3995 }
3996 else
3997 return first;
3998 break;
3999 case 'I':
4000 t1 = parse_template_args(t0, last, db);
4001 if (t1 != t0 && t1 != last)
4002 {
4003 auto name = db.names.back().move_full();
4004 db.names.pop_back();
4005 db.names.back().first += name;
4006 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
4007 t0 = t1;
Richard Smith24ecd092014-05-12 18:44:13 +00004008 component_ends_with_template_args = true;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004009 }
4010 else
4011 return first;
4012 break;
4013 case 'L':
4014 if (++t0 == last)
4015 return first;
4016 break;
4017 default:
4018 do_parse_unqualified_name:
4019 t1 = parse_unqualified_name(t0, last, db);
4020 if (t1 != t0 && t1 != last)
4021 {
4022 auto name = db.names.back().move_full();
4023 db.names.pop_back();
4024 if (!db.names.back().first.empty())
4025 db.names.back().first += "::" + name;
4026 else
4027 db.names.back().first = name;
4028 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
4029 pop_subs = true;
4030 t0 = t1;
4031 }
4032 else
4033 return first;
4034 }
4035 }
4036 first = t0 + 1;
4037 db.cv = cv;
Howard Hinnantf6725172013-06-21 17:04:24 +00004038 if (pop_subs && !db.subs.empty())
Howard Hinnant6c33e762013-06-17 18:10:34 +00004039 db.subs.pop_back();
Richard Smith24ecd092014-05-12 18:44:13 +00004040 if (ends_with_template_args)
4041 *ends_with_template_args = component_ends_with_template_args;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004042 }
4043 return first;
4044}
4045
4046// <discriminator> := _ <non-negative number> # when number < 10
4047// := __ <non-negative number> _ # when number >= 10
4048// extension := decimal-digit+
4049
4050const char*
4051parse_discriminator(const char* first, const char* last)
4052{
4053 // parse but ignore discriminator
4054 if (first != last)
4055 {
4056 if (*first == '_')
4057 {
4058 const char* t1 = first+1;
4059 if (t1 != last)
4060 {
4061 if (std::isdigit(*t1))
4062 first = t1+1;
4063 else if (*t1 == '_')
4064 {
4065 for (++t1; t1 != last && std::isdigit(*t1); ++t1)
4066 ;
4067 if (t1 != last && *t1 == '_')
4068 first = t1 + 1;
4069 }
4070 }
4071 }
4072 else if (std::isdigit(*first))
4073 {
4074 const char* t1 = first+1;
4075 for (; t1 != last && std::isdigit(*t1); ++t1)
4076 ;
4077 first = t1;
4078 }
4079 }
4080 return first;
4081}
4082
4083// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
4084// := Z <function encoding> E s [<discriminator>]
4085// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
4086
4087template <class C>
4088const char*
Richard Smith24ecd092014-05-12 18:44:13 +00004089parse_local_name(const char* first, const char* last, C& db,
4090 bool* ends_with_template_args)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004091{
4092 if (first != last && *first == 'Z')
4093 {
4094 const char* t = parse_encoding(first+1, last, db);
4095 if (t != first+1 && t != last && *t == 'E' && ++t != last)
4096 {
4097 switch (*t)
4098 {
4099 case 's':
4100 first = parse_discriminator(t+1, last);
Howard Hinnant753a30d2013-12-11 19:44:25 +00004101 if (db.names.empty())
4102 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004103 db.names.back().first.append("::string literal");
4104 break;
4105 case 'd':
4106 if (++t != last)
4107 {
4108 const char* t1 = parse_number(t, last);
4109 if (t1 != last && *t1 == '_')
4110 {
4111 t = t1 + 1;
Richard Smith24ecd092014-05-12 18:44:13 +00004112 t1 = parse_name(t, last, db,
4113 ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004114 if (t1 != t)
4115 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004116 if (db.names.size() < 2)
4117 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004118 auto name = db.names.back().move_full();
4119 db.names.pop_back();
4120 db.names.back().first.append("::");
4121 db.names.back().first.append(name);
4122 first = t1;
4123 }
4124 else
4125 db.names.pop_back();
4126 }
4127 }
4128 break;
4129 default:
4130 {
Richard Smith24ecd092014-05-12 18:44:13 +00004131 const char* t1 = parse_name(t, last, db,
4132 ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004133 if (t1 != t)
4134 {
4135 // parse but ignore discriminator
4136 first = parse_discriminator(t1, last);
Howard Hinnant753a30d2013-12-11 19:44:25 +00004137 if (db.names.size() < 2)
4138 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004139 auto name = db.names.back().move_full();
4140 db.names.pop_back();
4141 db.names.back().first.append("::");
4142 db.names.back().first.append(name);
4143 }
4144 else
4145 db.names.pop_back();
4146 }
4147 break;
4148 }
4149 }
4150 }
4151 return first;
4152}
4153
4154// <name> ::= <nested-name> // N
4155// ::= <local-name> # See Scope Encoding below // Z
4156// ::= <unscoped-template-name> <template-args>
4157// ::= <unscoped-name>
4158
4159// <unscoped-template-name> ::= <unscoped-name>
4160// ::= <substitution>
4161
4162template <class C>
4163const char*
Richard Smith24ecd092014-05-12 18:44:13 +00004164parse_name(const char* first, const char* last, C& db,
4165 bool* ends_with_template_args)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004166{
4167 if (last - first >= 2)
4168 {
4169 const char* t0 = first;
4170 // extension: ignore L here
4171 if (*t0 == 'L')
4172 ++t0;
4173 switch (*t0)
4174 {
4175 case 'N':
4176 {
Richard Smith24ecd092014-05-12 18:44:13 +00004177 const char* t1 = parse_nested_name(t0, last, db,
4178 ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004179 if (t1 != t0)
4180 first = t1;
4181 break;
4182 }
4183 case 'Z':
4184 {
Richard Smith24ecd092014-05-12 18:44:13 +00004185 const char* t1 = parse_local_name(t0, last, db,
4186 ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004187 if (t1 != t0)
4188 first = t1;
4189 break;
4190 }
4191 default:
4192 {
4193 const char* t1 = parse_unscoped_name(t0, last, db);
4194 if (t1 != t0)
4195 {
4196 if (t1 != last && *t1 == 'I') // <unscoped-template-name> <template-args>
4197 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004198 if (db.names.empty())
4199 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004200 db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
4201 t0 = t1;
4202 t1 = parse_template_args(t0, last, db);
4203 if (t1 != t0)
4204 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004205 if (db.names.size() < 2)
4206 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004207 auto tmp = db.names.back().move_full();
4208 db.names.pop_back();
4209 db.names.back().first += tmp;
4210 first = t1;
Richard Smith24ecd092014-05-12 18:44:13 +00004211 if (ends_with_template_args)
4212 *ends_with_template_args = true;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004213 }
4214 }
4215 else // <unscoped-name>
4216 first = t1;
4217 }
4218 else
4219 { // try <substitution> <template-args>
4220 t1 = parse_substitution(t0, last, db);
Howard Hinnantb4033ff2013-06-20 01:55:07 +00004221 if (t1 != t0 && t1 != last && *t1 == 'I')
Howard Hinnant6c33e762013-06-17 18:10:34 +00004222 {
4223 t0 = t1;
4224 t1 = parse_template_args(t0, last, db);
4225 if (t1 != t0)
4226 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004227 if (db.names.size() < 2)
4228 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004229 auto tmp = db.names.back().move_full();
4230 db.names.pop_back();
4231 db.names.back().first += tmp;
4232 first = t1;
Richard Smith24ecd092014-05-12 18:44:13 +00004233 if (ends_with_template_args)
4234 *ends_with_template_args = true;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004235 }
4236 }
4237 }
4238 break;
4239 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004240 }
4241 }
4242 return first;
4243}
4244
4245// <call-offset> ::= h <nv-offset> _
4246// ::= v <v-offset> _
4247//
4248// <nv-offset> ::= <offset number>
4249// # non-virtual base override
4250//
4251// <v-offset> ::= <offset number> _ <virtual offset number>
4252// # virtual base override, with vcall offset
4253
4254const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004255parse_call_offset(const char* first, const char* last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004256{
4257 if (first != last)
4258 {
4259 switch (*first)
4260 {
4261 case 'h':
4262 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004263 const char* t = parse_number(first + 1, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004264 if (t != first + 1 && t != last && *t == '_')
4265 first = t + 1;
4266 }
4267 break;
4268 case 'v':
4269 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004270 const char* t = parse_number(first + 1, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004271 if (t != first + 1 && t != last && *t == '_')
4272 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004273 const char* t2 = parse_number(++t, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004274 if (t2 != t && t2 != last && *t2 == '_')
4275 first = t2 + 1;
4276 }
4277 }
4278 break;
4279 }
4280 }
4281 return first;
4282}
4283
4284// <special-name> ::= TV <type> # virtual table
4285// ::= TT <type> # VTT structure (construction vtable index)
4286// ::= TI <type> # typeinfo structure
4287// ::= TS <type> # typeinfo name (null-terminated byte string)
4288// ::= Tc <call-offset> <call-offset> <base encoding>
4289// # base is the nominal target function of thunk
4290// # first call-offset is 'this' adjustment
4291// # second call-offset is result adjustment
4292// ::= T <call-offset> <base encoding>
4293// # base is the nominal target function of thunk
4294// ::= GV <object name> # Guard variable for one-time initialization
4295// # No <type>
Howard Hinnantf2700352011-12-09 20:07:56 +00004296// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
4297// extension ::= GR <object name> # reference temporary for object
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004298
Howard Hinnant6c33e762013-06-17 18:10:34 +00004299template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004300const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004301parse_special_name(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004302{
4303 if (last - first > 2)
4304 {
4305 const char* t;
4306 switch (*first)
4307 {
4308 case 'T':
4309 switch (first[1])
4310 {
4311 case 'V':
4312 // TV <type> # virtual table
Howard Hinnant6c33e762013-06-17 18:10:34 +00004313 t = parse_type(first+2, last, db);
4314 if (t != first+2)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004315 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004316 if (db.names.empty())
4317 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004318 db.names.back().first.insert(0, "vtable for ");
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004319 first = t;
4320 }
4321 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004322 case 'T':
4323 // TT <type> # VTT structure (construction vtable index)
4324 t = parse_type(first+2, last, db);
Howard Hinnantf2700352011-12-09 20:07:56 +00004325 if (t != first+2)
4326 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004327 if (db.names.empty())
4328 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004329 db.names.back().first.insert(0, "VTT for ");
4330 first = t;
4331 }
4332 break;
4333 case 'I':
4334 // TI <type> # typeinfo structure
4335 t = parse_type(first+2, last, db);
4336 if (t != first+2)
4337 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004338 if (db.names.empty())
4339 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004340 db.names.back().first.insert(0, "typeinfo for ");
4341 first = t;
4342 }
4343 break;
4344 case 'S':
4345 // TS <type> # typeinfo name (null-terminated byte string)
4346 t = parse_type(first+2, last, db);
4347 if (t != first+2)
4348 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004349 if (db.names.empty())
4350 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004351 db.names.back().first.insert(0, "typeinfo name for ");
4352 first = t;
4353 }
4354 break;
4355 case 'c':
4356 // Tc <call-offset> <call-offset> <base encoding>
4357 {
4358 const char* t0 = parse_call_offset(first+2, last);
4359 if (t0 == first+2)
4360 break;
4361 const char* t1 = parse_call_offset(t0, last);
4362 if (t1 == t0)
4363 break;
4364 t = parse_encoding(t1, last, db);
4365 if (t != t1)
4366 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004367 if (db.names.empty())
4368 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004369 db.names.back().first.insert(0, "covariant return thunk to ");
4370 first = t;
4371 }
4372 }
4373 break;
4374 case 'C':
4375 // extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
4376 t = parse_type(first+2, last, db);
4377 if (t != first+2)
4378 {
4379 const char* t0 = parse_number(t, last);
Howard Hinnantf2700352011-12-09 20:07:56 +00004380 if (t0 != t && t0 != last && *t0 == '_')
4381 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004382 const char* t1 = parse_type(++t0, last, db);
Howard Hinnantf2700352011-12-09 20:07:56 +00004383 if (t1 != t0)
4384 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004385 if (db.names.size() < 2)
4386 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004387 auto left = db.names.back().move_full();
4388 db.names.pop_back();
4389 db.names.back().first = "construction vtable for " +
4390 std::move(left) + "-in-" +
4391 db.names.back().move_full();
4392 first = t1;
Howard Hinnantf2700352011-12-09 20:07:56 +00004393 }
4394 }
4395 }
4396 break;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004397 default:
4398 // T <call-offset> <base encoding>
4399 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004400 const char* t0 = parse_call_offset(first+1, last);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004401 if (t0 == first+1)
4402 break;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004403 t = parse_encoding(t0, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004404 if (t != t0)
4405 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004406 if (db.names.empty())
4407 return first;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004408 if (first[2] == 'v')
4409 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004410 db.names.back().first.insert(0, "virtual thunk to ");
4411 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004412 }
4413 else
4414 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004415 db.names.back().first.insert(0, "non-virtual thunk to ");
4416 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004417 }
4418 }
4419 }
4420 break;
4421 }
4422 break;
4423 case 'G':
Howard Hinnantf2700352011-12-09 20:07:56 +00004424 switch (first[1])
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004425 {
Howard Hinnantf2700352011-12-09 20:07:56 +00004426 case 'V':
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004427 // GV <object name> # Guard variable for one-time initialization
Howard Hinnant6c33e762013-06-17 18:10:34 +00004428 t = parse_name(first+2, last, db);
4429 if (t != first+2)
4430 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004431 if (db.names.empty())
4432 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004433 db.names.back().first.insert(0, "guard variable for ");
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004434 first = t;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004435 }
Howard Hinnantf2700352011-12-09 20:07:56 +00004436 break;
4437 case 'R':
4438 // extension ::= GR <object name> # reference temporary for object
Howard Hinnant6c33e762013-06-17 18:10:34 +00004439 t = parse_name(first+2, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004440 if (t != first+2)
4441 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004442 if (db.names.empty())
4443 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004444 db.names.back().first.insert(0, "reference temporary for ");
4445 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004446 }
4447 break;
4448 }
4449 break;
4450 }
4451 }
4452 return first;
4453}
4454
Howard Hinnant753a30d2013-12-11 19:44:25 +00004455template <class T>
4456class save_value
4457{
4458 T& restore_;
4459 T original_value_;
4460public:
4461 save_value(T& restore)
4462 : restore_(restore),
4463 original_value_(restore)
4464 {}
4465
4466 ~save_value()
4467 {
4468 restore_ = std::move(original_value_);
4469 }
4470
4471 save_value(const save_value&) = delete;
4472 save_value& operator=(const save_value&) = delete;
4473};
4474
Howard Hinnant6c33e762013-06-17 18:10:34 +00004475// <encoding> ::= <function name> <bare-function-type>
4476// ::= <data name>
4477// ::= <special-name>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004478
Howard Hinnant6c33e762013-06-17 18:10:34 +00004479template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004480const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004481parse_encoding(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004482{
4483 if (first != last)
4484 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004485 save_value<decltype(db.encoding_depth)> su(db.encoding_depth);
4486 ++db.encoding_depth;
4487 save_value<decltype(db.tag_templates)> sb(db.tag_templates);
4488 if (db.encoding_depth > 1)
4489 db.tag_templates = true;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004490 switch (*first)
4491 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004492 case 'G':
4493 case 'T':
4494 first = parse_special_name(first, last, db);
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004495 break;
4496 default:
Howard Hinnant6c33e762013-06-17 18:10:34 +00004497 {
Richard Smith24ecd092014-05-12 18:44:13 +00004498 bool ends_with_template_args = false;
4499 const char* t = parse_name(first, last, db,
4500 &ends_with_template_args);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004501 unsigned cv = db.cv;
4502 unsigned ref = db.ref;
4503 if (t != first)
Howard Hinnantab87dcf2011-12-15 20:02:15 +00004504 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004505 if (t != last && *t != 'E' && *t != '.')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004506 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004507 save_value<bool> sb2(db.tag_templates);
Howard Hinnant6c33e762013-06-17 18:10:34 +00004508 db.tag_templates = false;
4509 const char* t2;
4510 typename C::String ret2;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004511 if (db.names.empty())
4512 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004513 const typename C::String& nm = db.names.back().first;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004514 if (nm.empty())
4515 return first;
Richard Smith24ecd092014-05-12 18:44:13 +00004516 if (!db.parsed_ctor_dtor_cv && ends_with_template_args)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004517 {
4518 t2 = parse_type(t, last, db);
4519 if (t2 == t)
4520 return first;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004521 if (db.names.size() < 2)
4522 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004523 auto ret1 = std::move(db.names.back().first);
4524 ret2 = std::move(db.names.back().second);
4525 if (ret2.empty())
4526 ret1 += ' ';
4527 db.names.pop_back();
4528 db.names.back().first.insert(0, ret1);
4529 t = t2;
4530 }
4531 db.names.back().first += '(';
4532 if (t != last && *t == 'v')
4533 {
4534 ++t;
4535 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004536 else
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004537 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004538 bool first_arg = true;
4539 while (true)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004540 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004541 size_t k0 = db.names.size();
4542 t2 = parse_type(t, last, db);
4543 size_t k1 = db.names.size();
4544 if (t2 == t)
4545 break;
4546 if (k1 > k0)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004547 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004548 typename C::String tmp;
4549 for (size_t k = k0; k < k1; ++k)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004550 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004551 if (!tmp.empty())
4552 tmp += ", ";
4553 tmp += db.names[k].move_full();
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004554 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004555 for (size_t k = k0; k < k1; ++k)
4556 db.names.pop_back();
4557 if (!tmp.empty())
4558 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004559 if (db.names.empty())
4560 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004561 if (!first_arg)
4562 db.names.back().first += ", ";
4563 else
4564 first_arg = false;
4565 db.names.back().first += tmp;
4566 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004567 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004568 t = t2;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004569 }
4570 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00004571 if (db.names.empty())
4572 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004573 db.names.back().first += ')';
4574 if (cv & 1)
4575 db.names.back().first.append(" const");
4576 if (cv & 2)
4577 db.names.back().first.append(" volatile");
4578 if (cv & 4)
4579 db.names.back().first.append(" restrict");
4580 if (ref == 1)
4581 db.names.back().first.append(" &");
4582 else if (ref == 2)
4583 db.names.back().first.append(" &&");
4584 db.names.back().first += ret2;
4585 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004586 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004587 else
4588 first = t;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004589 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004590 break;
4591 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004592 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004593 }
4594 return first;
4595}
4596
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004597// _block_invoke
4598// _block_invoke<decimal-digit>+
4599// _block_invoke_<decimal-digit>+
4600
Howard Hinnant6c33e762013-06-17 18:10:34 +00004601template <class C>
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004602const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004603parse_block_invoke(const char* first, const char* last, C& db)
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004604{
4605 if (last - first >= 13)
4606 {
4607 const char test[] = "_block_invoke";
4608 const char* t = first;
4609 for (int i = 0; i < 13; ++i, ++t)
4610 {
4611 if (*t != test[i])
4612 return first;
4613 }
4614 if (t != last)
4615 {
4616 if (*t == '_')
4617 {
4618 // must have at least 1 decimal digit
Howard Hinnant6c33e762013-06-17 18:10:34 +00004619 if (++t == last || !std::isdigit(*t))
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004620 return first;
4621 ++t;
4622 }
4623 // parse zero or more digits
4624 while (t != last && isdigit(*t))
4625 ++t;
4626 }
Howard Hinnant753a30d2013-12-11 19:44:25 +00004627 if (db.names.empty())
4628 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004629 db.names.back().first.insert(0, "invocation function for block in ");
4630 first = t;
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004631 }
4632 return first;
4633}
4634
Howard Hinnant6c33e762013-06-17 18:10:34 +00004635// extension
4636// <dot-suffix> := .<anything and everything>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004637
Howard Hinnant6c33e762013-06-17 18:10:34 +00004638template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004639const char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004640parse_dot_suffix(const char* first, const char* last, C& db)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004641{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004642 if (first != last && *first == '.')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004643 {
Howard Hinnant753a30d2013-12-11 19:44:25 +00004644 if (db.names.empty())
4645 return first;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004646 db.names.back().first += " (" + typename C::String(first, last) + ")";
4647 first = last;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004648 }
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004649 return first;
4650}
4651
Howard Hinnant5dd173b2013-04-10 19:44:03 +00004652// <block-involcaton-function> ___Z<encoding>_block_invoke
4653// <block-involcaton-function> ___Z<encoding>_block_invoke<decimal-digit>+
4654// <block-involcaton-function> ___Z<encoding>_block_invoke_<decimal-digit>+
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004655// <mangled-name> ::= _Z<encoding>
4656// ::= <type>
4657
Howard Hinnant6c33e762013-06-17 18:10:34 +00004658template <class C>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004659void
Howard Hinnant6c33e762013-06-17 18:10:34 +00004660demangle(const char* first, const char* last, C& db, int& status)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004661{
Howard Hinnanteb8d46c2013-06-23 17:14:35 +00004662 if (first >= last)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004663 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004664 status = invalid_mangled_name;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004665 return;
4666 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004667 if (*first == '_')
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004668 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004669 if (last - first >= 4)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004670 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004671 if (first[1] == 'Z')
4672 {
4673 const char* t = parse_encoding(first+2, last, db);
4674 if (t != first+2 && t != last && *t == '.')
4675 t = parse_dot_suffix(t, last, db);
4676 if (t != last)
4677 status = invalid_mangled_name;
4678 }
4679 else if (first[1] == '_' && first[2] == '_' && first[3] == 'Z')
4680 {
4681 const char* t = parse_encoding(first+4, last, db);
4682 if (t != first+4 && t != last)
4683 {
4684 const char* t1 = parse_block_invoke(t, last, db);
4685 if (t1 != last)
4686 status = invalid_mangled_name;
4687 }
4688 else
4689 status = invalid_mangled_name;
4690 }
4691 else
4692 status = invalid_mangled_name;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004693 }
4694 else
Howard Hinnant6c33e762013-06-17 18:10:34 +00004695 status = invalid_mangled_name;
4696 }
4697 else
4698 {
4699 const char* t = parse_type(first, last, db);
4700 if (t != last)
4701 status = invalid_mangled_name;
4702 }
Howard Hinnanteb8d46c2013-06-23 17:14:35 +00004703 if (status == success && db.names.empty())
4704 status = invalid_mangled_name;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004705}
4706
Howard Hinnant6c33e762013-06-17 18:10:34 +00004707template <std::size_t N>
4708class arena
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004709{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004710 static const std::size_t alignment = 16;
4711 alignas(alignment) char buf_[N];
4712 char* ptr_;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004713
Howard Hinnant6c33e762013-06-17 18:10:34 +00004714 std::size_t
4715 align_up(std::size_t n) noexcept
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +00004716 {return (n + (alignment-1)) & ~(alignment-1);}
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004717
Howard Hinnant6c33e762013-06-17 18:10:34 +00004718 bool
4719 pointer_in_buffer(char* p) noexcept
4720 {return buf_ <= p && p <= buf_ + N;}
4721
4722public:
4723 arena() noexcept : ptr_(buf_) {}
4724 ~arena() {ptr_ = nullptr;}
4725 arena(const arena&) = delete;
4726 arena& operator=(const arena&) = delete;
4727
4728 char* allocate(std::size_t n);
4729 void deallocate(char* p, std::size_t n) noexcept;
4730
4731 static constexpr std::size_t size() {return N;}
4732 std::size_t used() const {return static_cast<std::size_t>(ptr_ - buf_);}
4733 void reset() {ptr_ = buf_;}
4734};
4735
4736template <std::size_t N>
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004737char*
Howard Hinnant6c33e762013-06-17 18:10:34 +00004738arena<N>::allocate(std::size_t n)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004739{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004740 n = align_up(n);
4741 if (static_cast<std::size_t>(buf_ + N - ptr_) >= n)
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004742 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004743 char* r = ptr_;
4744 ptr_ += n;
4745 return r;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004746 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004747 return static_cast<char*>(std::malloc(n));
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004748}
4749
Howard Hinnant6c33e762013-06-17 18:10:34 +00004750template <std::size_t N>
4751void
4752arena<N>::deallocate(char* p, std::size_t n) noexcept
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004753{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004754 if (pointer_in_buffer(p))
4755 {
4756 n = align_up(n);
4757 if (p + n == ptr_)
4758 ptr_ = p;
4759 }
4760 else
4761 std::free(p);
4762}
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004763
Howard Hinnant6c33e762013-06-17 18:10:34 +00004764template <class T, std::size_t N>
4765class short_alloc
4766{
4767 arena<N>& a_;
4768public:
4769 typedef T value_type;
4770
4771public:
4772 template <class _Up> struct rebind {typedef short_alloc<_Up, N> other;};
4773
4774 short_alloc(arena<N>& a) noexcept : a_(a) {}
4775 template <class U>
4776 short_alloc(const short_alloc<U, N>& a) noexcept
4777 : a_(a.a_) {}
4778 short_alloc(const short_alloc&) = default;
4779 short_alloc& operator=(const short_alloc&) = delete;
4780
4781 T* allocate(std::size_t n)
4782 {
4783 return reinterpret_cast<T*>(a_.allocate(n*sizeof(T)));
4784 }
4785 void deallocate(T* p, std::size_t n) noexcept
4786 {
4787 a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
4788 }
4789
4790 template <class T1, std::size_t N1, class U, std::size_t M>
4791 friend
4792 bool
4793 operator==(const short_alloc<T1, N1>& x, const short_alloc<U, M>& y) noexcept;
4794
4795 template <class U, std::size_t M> friend class short_alloc;
4796};
4797
4798template <class T, std::size_t N, class U, std::size_t M>
4799inline
4800bool
4801operator==(const short_alloc<T, N>& x, const short_alloc<U, M>& y) noexcept
4802{
4803 return N == M && &x.a_ == &y.a_;
4804}
4805
4806template <class T, std::size_t N, class U, std::size_t M>
4807inline
4808bool
4809operator!=(const short_alloc<T, N>& x, const short_alloc<U, M>& y) noexcept
4810{
4811 return !(x == y);
4812}
4813
4814template <class T>
4815class malloc_alloc
4816{
4817public:
4818 typedef T value_type;
4819
4820 malloc_alloc() = default;
4821 template <class U> malloc_alloc(const malloc_alloc<U>&) noexcept {}
4822
4823 T* allocate(std::size_t n)
4824 {
4825 return static_cast<T*>(std::malloc(n*sizeof(T)));
4826 }
4827 void deallocate(T* p, std::size_t) noexcept
4828 {
4829 std::free(p);
4830 }
4831};
4832
4833template <class T, class U>
4834inline
4835bool
4836operator==(const malloc_alloc<T>&, const malloc_alloc<U>&) noexcept
4837{
4838 return true;
4839}
4840
4841template <class T, class U>
4842inline
4843bool
4844operator!=(const malloc_alloc<T>& x, const malloc_alloc<U>& y) noexcept
4845{
4846 return !(x == y);
4847}
4848
4849const size_t bs = 4 * 1024;
4850template <class T> using Alloc = short_alloc<T, bs>;
4851template <class T> using Vector = std::vector<T, Alloc<T>>;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004852
Nico Weber2b683fb2014-05-30 17:27:21 +00004853template <class StrT>
Howard Hinnant6c33e762013-06-17 18:10:34 +00004854struct string_pair
4855{
Nico Weber2b683fb2014-05-30 17:27:21 +00004856 StrT first;
4857 StrT second;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004858
4859 string_pair() = default;
Nico Weber2b683fb2014-05-30 17:27:21 +00004860 string_pair(StrT f) : first(std::move(f)) {}
4861 string_pair(StrT f, StrT s)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004862 : first(std::move(f)), second(std::move(s)) {}
4863 template <size_t N>
4864 string_pair(const char (&s)[N]) : first(s, N-1) {}
4865
4866 size_t size() const {return first.size() + second.size();}
Nico Weber2b683fb2014-05-30 17:27:21 +00004867 StrT full() const {return first + second;}
4868 StrT move_full() {return std::move(first) + std::move(second);}
Howard Hinnant6c33e762013-06-17 18:10:34 +00004869};
4870
Howard Hinnant061240c2013-10-22 16:45:48 +00004871struct Db
4872{
Nico Weber2b683fb2014-05-30 17:27:21 +00004873 typedef std::basic_string<char, std::char_traits<char>,
4874 malloc_alloc<char>> String;
4875 typedef Vector<string_pair<String>> sub_type;
Howard Hinnant061240c2013-10-22 16:45:48 +00004876 typedef Vector<sub_type> template_param_type;
Nico Weber2b683fb2014-05-30 17:27:21 +00004877 sub_type names;
4878 template_param_type subs;
Howard Hinnant061240c2013-10-22 16:45:48 +00004879 Vector<template_param_type> template_param;
4880 unsigned cv;
4881 unsigned ref;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004882 unsigned encoding_depth;
Howard Hinnant061240c2013-10-22 16:45:48 +00004883 bool parsed_ctor_dtor_cv;
4884 bool tag_templates;
4885 bool fix_forward_references;
4886 bool try_to_parse_template_args;
4887
4888 template <size_t N>
4889 Db(arena<N>& ar) :
4890 names(ar),
4891 subs(0, names, ar),
4892 template_param(0, subs, ar)
4893 {}
4894};
4895
Howard Hinnant6c33e762013-06-17 18:10:34 +00004896} // unnamed namespace
4897
Howard Hinnant6c33e762013-06-17 18:10:34 +00004898extern "C"
Nico Weber298baa32014-06-25 23:55:37 +00004899__attribute__ ((__visibility__("default")))
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004900char*
4901__cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status)
4902{
Howard Hinnant6c33e762013-06-17 18:10:34 +00004903 if (mangled_name == nullptr || (buf != nullptr && n == nullptr))
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004904 {
4905 if (status)
Howard Hinnant6c33e762013-06-17 18:10:34 +00004906 *status = invalid_args;
4907 return nullptr;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004908 }
Howard Hinnant8ad6a222013-07-26 22:14:53 +00004909 size_t internal_size = buf != nullptr ? *n : 0;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004910 arena<bs> a;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004911 Db db(a);
4912 db.cv = 0;
Howard Hinnant19e36dd2013-06-19 13:43:18 +00004913 db.ref = 0;
Howard Hinnant753a30d2013-12-11 19:44:25 +00004914 db.encoding_depth = 0;
Howard Hinnant6c33e762013-06-17 18:10:34 +00004915 db.parsed_ctor_dtor_cv = false;
4916 db.tag_templates = true;
4917 db.template_param.emplace_back(a);
4918 db.fix_forward_references = false;
4919 db.try_to_parse_template_args = true;
4920 int internal_status = success;
Howard Hinnantb2d1f942013-06-23 19:52:45 +00004921 size_t len = std::strlen(mangled_name);
4922 demangle(mangled_name, mangled_name + len, db,
Howard Hinnant6c33e762013-06-17 18:10:34 +00004923 internal_status);
Howard Hinnantb2d1f942013-06-23 19:52:45 +00004924 if (internal_status == success && db.fix_forward_references &&
4925 !db.template_param.empty() && !db.template_param.front().empty())
4926 {
4927 db.fix_forward_references = false;
4928 db.tag_templates = false;
4929 db.names.clear();
4930 db.subs.clear();
4931 demangle(mangled_name, mangled_name + len, db, internal_status);
4932 if (db.fix_forward_references)
4933 internal_status = invalid_mangled_name;
4934 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004935 if (internal_status == success)
4936 {
4937 size_t sz = db.names.back().size() + 1;
4938 if (sz > internal_size)
4939 {
4940 char* newbuf = static_cast<char*>(std::realloc(buf, sz));
4941 if (newbuf == nullptr)
4942 {
4943 internal_status = memory_alloc_failure;
4944 buf = nullptr;
4945 }
4946 else
Howard Hinnant8ad6a222013-07-26 22:14:53 +00004947 {
Howard Hinnant6c33e762013-06-17 18:10:34 +00004948 buf = newbuf;
Howard Hinnant8ad6a222013-07-26 22:14:53 +00004949 if (n != nullptr)
4950 *n = sz;
4951 }
Howard Hinnant6c33e762013-06-17 18:10:34 +00004952 }
4953 if (buf != nullptr)
4954 {
4955 db.names.back().first += db.names.back().second;
4956 std::memcpy(buf, db.names.back().first.data(), sz-1);
4957 buf[sz-1] = char(0);
4958 }
4959 }
4960 else
4961 buf = nullptr;
4962 if (status)
4963 *status = internal_status;
Howard Hinnantd213ffd2011-05-05 15:27:28 +00004964 return buf;
4965}
4966
Howard Hinnant6c33e762013-06-17 18:10:34 +00004967} // __cxxabiv1