Coverage Report

Created: 2025-11-24 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/brpc/src/butil/third_party/symbolize/demangle.cc
Line
Count
Source
1
// Copyright (c) 2006, Google Inc.
2
// All rights reserved.
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are
6
// met:
7
//
8
//     * Redistributions of source code must retain the above copyright
9
// notice, this list of conditions and the following disclaimer.
10
//     * Redistributions in binary form must reproduce the above
11
// copyright notice, this list of conditions and the following disclaimer
12
// in the documentation and/or other materials provided with the
13
// distribution.
14
//     * Neither the name of Google Inc. nor the names of its
15
// contributors may be used to endorse or promote products derived from
16
// this software without specific prior written permission.
17
//
18
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
//
30
// Author: Satoru Takabayashi
31
//
32
// For reference check out:
33
// http://www.codesourcery.com/public/cxx-abi/abi.html#mangling
34
//
35
// Note that we only have partial C++0x support yet.
36
37
#include <stdio.h>  // for NULL
38
#include "demangle.h"
39
40
_START_GOOGLE_NAMESPACE_
41
42
typedef struct {
43
  const char *abbrev;
44
  const char *real_name;
45
} AbbrevPair;
46
47
// List of operators from Itanium C++ ABI.
48
static const AbbrevPair kOperatorList[] = {
49
  { "nw", "new" },
50
  { "na", "new[]" },
51
  { "dl", "delete" },
52
  { "da", "delete[]" },
53
  { "ps", "+" },
54
  { "ng", "-" },
55
  { "ad", "&" },
56
  { "de", "*" },
57
  { "co", "~" },
58
  { "pl", "+" },
59
  { "mi", "-" },
60
  { "ml", "*" },
61
  { "dv", "/" },
62
  { "rm", "%" },
63
  { "an", "&" },
64
  { "or", "|" },
65
  { "eo", "^" },
66
  { "aS", "=" },
67
  { "pL", "+=" },
68
  { "mI", "-=" },
69
  { "mL", "*=" },
70
  { "dV", "/=" },
71
  { "rM", "%=" },
72
  { "aN", "&=" },
73
  { "oR", "|=" },
74
  { "eO", "^=" },
75
  { "ls", "<<" },
76
  { "rs", ">>" },
77
  { "lS", "<<=" },
78
  { "rS", ">>=" },
79
  { "eq", "==" },
80
  { "ne", "!=" },
81
  { "lt", "<" },
82
  { "gt", ">" },
83
  { "le", "<=" },
84
  { "ge", ">=" },
85
  { "nt", "!" },
86
  { "aa", "&&" },
87
  { "oo", "||" },
88
  { "pp", "++" },
89
  { "mm", "--" },
90
  { "cm", "," },
91
  { "pm", "->*" },
92
  { "pt", "->" },
93
  { "cl", "()" },
94
  { "ix", "[]" },
95
  { "qu", "?" },
96
  { "st", "sizeof" },
97
  { "sz", "sizeof" },
98
  { NULL, NULL },
99
};
100
101
// List of builtin types from Itanium C++ ABI.
102
static const AbbrevPair kBuiltinTypeList[] = {
103
  { "v", "void" },
104
  { "w", "wchar_t" },
105
  { "b", "bool" },
106
  { "c", "char" },
107
  { "a", "signed char" },
108
  { "h", "unsigned char" },
109
  { "s", "short" },
110
  { "t", "unsigned short" },
111
  { "i", "int" },
112
  { "j", "unsigned int" },
113
  { "l", "long" },
114
  { "m", "unsigned long" },
115
  { "x", "long long" },
116
  { "y", "unsigned long long" },
117
  { "n", "__int128" },
118
  { "o", "unsigned __int128" },
119
  { "f", "float" },
120
  { "d", "double" },
121
  { "e", "long double" },
122
  { "g", "__float128" },
123
  { "z", "ellipsis" },
124
  { NULL, NULL }
125
};
126
127
// List of substitutions Itanium C++ ABI.
128
static const AbbrevPair kSubstitutionList[] = {
129
  { "St", "" },
130
  { "Sa", "allocator" },
131
  { "Sb", "basic_string" },
132
  // std::basic_string<char, std::char_traits<char>,std::allocator<char> >
133
  { "Ss", "string"},
134
  // std::basic_istream<char, std::char_traits<char> >
135
  { "Si", "istream" },
136
  // std::basic_ostream<char, std::char_traits<char> >
137
  { "So", "ostream" },
138
  // std::basic_iostream<char, std::char_traits<char> >
139
  { "Sd", "iostream" },
140
  { NULL, NULL }
141
};
142
143
// State needed for demangling.
144
typedef struct {
145
  const char *mangled_cur;  // Cursor of mangled name.
146
  char *out_cur;            // Cursor of output string.
147
  const char *out_begin;    // Beginning of output string.
148
  const char *out_end;      // End of output string.
149
  const char *prev_name;    // For constructors/destructors.
150
  int prev_name_length;     // For constructors/destructors.
151
  short nest_level;         // For nested names.
152
  bool append;              // Append flag.
153
  bool overflowed;          // True if output gets overflowed.
154
} State;
155
156
// We don't use strlen() in libc since it's not guaranteed to be async
157
// signal safe.
158
24.8k
static size_t StrLen(const char *str) {
159
24.8k
  size_t len = 0;
160
78.0k
  while (*str != '\0') {
161
53.2k
    ++str;
162
53.2k
    ++len;
163
53.2k
  }
164
24.8k
  return len;
165
24.8k
}
166
167
// Returns true if "str" has at least "n" characters remaining.
168
54.7k
static bool AtLeastNumCharsRemaining(const char *str, int n) {
169
205k
  for (int i = 0; i < n; ++i) {
170
157k
    if (str[i] == '\0') {
171
7.06k
      return false;
172
7.06k
    }
173
157k
  }
174
47.6k
  return true;
175
54.7k
}
176
177
// Returns true if "str" has "prefix" as a prefix.
178
230
static bool StrPrefix(const char *str, const char *prefix) {
179
230
  size_t i = 0;
180
230
  while (str[i] != '\0' && prefix[i] != '\0' &&
181
230
         str[i] == prefix[i]) {
182
0
    ++i;
183
0
  }
184
230
  return prefix[i] == '\0';  // Consumed everything in "prefix".
185
230
}
186
187
static void InitState(State *state, const char *mangled,
188
4.76k
                      char *out, int out_size) {
189
4.76k
  state->mangled_cur = mangled;
190
4.76k
  state->out_cur = out;
191
4.76k
  state->out_begin = out;
192
4.76k
  state->out_end = out + out_size;
193
4.76k
  state->prev_name  = NULL;
194
4.76k
  state->prev_name_length = -1;
195
4.76k
  state->nest_level = -1;
196
4.76k
  state->append = true;
197
4.76k
  state->overflowed = false;
198
4.76k
}
199
200
// Returns true and advances "mangled_cur" if we find "one_char_token"
201
// at "mangled_cur" position.  It is assumed that "one_char_token" does
202
// not contain '\0'.
203
571k
static bool ParseOneCharToken(State *state, const char one_char_token) {
204
571k
  if (state->mangled_cur[0] == one_char_token) {
205
53.2k
    ++state->mangled_cur;
206
53.2k
    return true;
207
53.2k
  }
208
518k
  return false;
209
571k
}
210
211
// Returns true and advances "mangled_cur" if we find "two_char_token"
212
// at "mangled_cur" position.  It is assumed that "two_char_token" does
213
// not contain '\0'.
214
173k
static bool ParseTwoCharToken(State *state, const char *two_char_token) {
215
173k
  if (state->mangled_cur[0] == two_char_token[0] &&
216
37.5k
      state->mangled_cur[1] == two_char_token[1]) {
217
4.45k
    state->mangled_cur += 2;
218
4.45k
    return true;
219
4.45k
  }
220
169k
  return false;
221
173k
}
222
223
// Returns true and advances "mangled_cur" if we find any character in
224
// "char_class" at "mangled_cur" position.
225
25.2k
static bool ParseCharClass(State *state, const char *char_class) {
226
25.2k
  const char *p = char_class;
227
122k
  for (; *p != '\0'; ++p) {
228
104k
    if (state->mangled_cur[0] == *p) {
229
7.40k
      ++state->mangled_cur;
230
7.40k
      return true;
231
7.40k
    }
232
104k
  }
233
17.8k
  return false;
234
25.2k
}
235
236
// This function is used for handling an optional non-terminal.
237
4.45k
static bool Optional(bool) {
238
4.45k
  return true;
239
4.45k
}
240
241
// This function is used for handling <non-terminal>+ syntax.
242
typedef bool (*ParseFunc)(State *);
243
4.45k
static bool OneOrMore(ParseFunc parse_func, State *state) {
244
4.45k
  if (parse_func(state)) {
245
13.3k
    while (parse_func(state)) {
246
8.91k
    }
247
4.45k
    return true;
248
4.45k
  }
249
0
  return false;
250
4.45k
}
251
252
// This function is used for handling <non-terminal>* syntax. The function
253
// always returns true and must be followed by a termination token or a
254
// terminating sequence not handled by parse_func (e.g.
255
// ParseOneCharToken(state, 'E')).
256
0
static bool ZeroOrMore(ParseFunc parse_func, State *state) {
257
0
  while (parse_func(state)) {
258
0
  }
259
0
  return true;
260
0
}
261
262
// Append "str" at "out_cur".  If there is an overflow, "overflowed"
263
// is set to true for later use.  The output string is ensured to
264
// always terminate with '\0' as long as there is no overflow.
265
38.6k
static void Append(State *state, const char * const str, const int length) {
266
38.6k
  int i;
267
176k
  for (i = 0; i < length; ++i) {
268
137k
    if (state->out_cur + 1 < state->out_end) {  // +1 for '\0'
269
137k
      *state->out_cur = str[i];
270
137k
      ++state->out_cur;
271
137k
    } else {
272
0
      state->overflowed = true;
273
0
      break;
274
0
    }
275
137k
  }
276
38.6k
  if (!state->overflowed) {
277
38.6k
    *state->out_cur = '\0';  // Terminate it with '\0'
278
38.6k
  }
279
38.6k
}
280
281
// We don't use equivalents in libc to avoid locale issues.
282
36.1k
static bool IsLower(char c) {
283
36.1k
  return c >= 'a' && c <= 'z';
284
36.1k
}
285
286
38.6k
static bool IsAlpha(char c) {
287
38.6k
  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
288
38.6k
}
289
290
76.9k
static bool IsDigit(char c) {
291
76.9k
  return c >= '0' && c <= '9';
292
76.9k
}
293
294
// Returns true if "str" is a function clone suffix.  These suffixes are used
295
// by GCC 4.5.x and later versions to indicate functions which have been
296
// cloned during optimization.  We treat any sequence (.<alpha>+.<digit>+)+ as
297
// a function clone suffix.
298
0
static bool IsFunctionCloneSuffix(const char *str) {
299
0
  size_t i = 0;
300
0
  while (str[i] != '\0') {
301
    // Consume a single .<alpha>+.<digit>+ sequence.
302
0
    if (str[i] != '.' || !IsAlpha(str[i + 1])) {
303
0
      return false;
304
0
    }
305
0
    i += 2;
306
0
    while (IsAlpha(str[i])) {
307
0
      ++i;
308
0
    }
309
0
    if (str[i] != '.' || !IsDigit(str[i + 1])) {
310
0
      return false;
311
0
    }
312
0
    i += 2;
313
0
    while (IsDigit(str[i])) {
314
0
      ++i;
315
0
    }
316
0
  }
317
0
  return true;  // Consumed everything in "str".
318
0
}
319
320
// Append "str" with some tweaks, iff "append" state is true.
321
// Returns true so that it can be placed in "if" conditions.
322
static void MaybeAppendWithLength(State *state, const char * const str,
323
39.6k
                                  const int length) {
324
39.6k
  if (state->append && length > 0) {
325
    // Append a space if the output buffer ends with '<' and "str"
326
    // starts with '<' to avoid <<<.
327
38.6k
    if (str[0] == '<' && state->out_begin < state->out_cur  &&
328
230
        state->out_cur[-1] == '<') {
329
0
      Append(state, " ", 1);
330
0
    }
331
    // Remember the last identifier name for ctors/dtors.
332
38.6k
    if (IsAlpha(str[0]) || str[0] == '_') {
333
17.3k
      state->prev_name = state->out_cur;
334
17.3k
      state->prev_name_length = length;
335
17.3k
    }
336
38.6k
    Append(state, str, length);
337
38.6k
  }
338
39.6k
}
339
340
// A convenient wrapper arount MaybeAppendWithLength().
341
48.6k
static bool MaybeAppend(State *state, const char * const str) {
342
48.6k
  if (state->append) {
343
24.8k
    int length = StrLen(str);
344
24.8k
    MaybeAppendWithLength(state, str, length);
345
24.8k
  }
346
48.6k
  return true;
347
48.6k
}
348
349
// This function is used for handling nested names.
350
4.45k
static bool EnterNestedName(State *state) {
351
4.45k
  state->nest_level = 0;
352
4.45k
  return true;
353
4.45k
}
354
355
// This function is used for handling nested names.
356
4.45k
static bool LeaveNestedName(State *state, short prev_value) {
357
4.45k
  state->nest_level = prev_value;
358
4.45k
  return true;
359
4.45k
}
360
361
// Disable the append mode not to print function parameters, etc.
362
15.2k
static bool DisableAppend(State *state) {
363
15.2k
  state->append = false;
364
15.2k
  return true;
365
15.2k
}
366
367
// Restore the append mode to the previous state.
368
4.45k
static bool RestoreAppend(State *state, bool prev_value) {
369
4.45k
  state->append = prev_value;
370
4.45k
  return true;
371
4.45k
}
372
373
// Increase the nest level for nested names.
374
19.2k
static void MaybeIncreaseNestLevel(State *state) {
375
19.2k
  if (state->nest_level > -1) {
376
19.2k
    ++state->nest_level;
377
19.2k
  }
378
19.2k
}
379
380
// Appends :: for nested names if necessary.
381
24.6k
static void MaybeAppendSeparator(State *state) {
382
24.6k
  if (state->nest_level >= 1) {
383
20.1k
    MaybeAppend(state, "::");
384
20.1k
  }
385
24.6k
}
386
387
// Cancel the last separator if necessary.
388
5.37k
static void MaybeCancelLastSeparator(State *state) {
389
5.37k
  if (state->nest_level >= 1 && state->append &&
390
3.76k
      state->out_begin <= state->out_cur - 2) {
391
3.76k
    state->out_cur -= 2;
392
3.76k
    *state->out_cur = '\0';
393
3.76k
  }
394
5.37k
}
395
396
// Returns true if the identifier of the given length pointed to by
397
// "mangled_cur" is anonymous namespace.
398
11.5k
static bool IdentifierIsAnonymousNamespace(State *state, int length) {
399
11.5k
  static const char anon_prefix[] = "_GLOBAL__N_";
400
11.5k
  return (length > (int)sizeof(anon_prefix) - 1 &&  // Should be longer.
401
230
          StrPrefix(state->mangled_cur, anon_prefix));
402
11.5k
}
403
404
// Forward declarations of our parsing functions.
405
static bool ParseMangledName(State *state);
406
static bool ParseEncoding(State *state);
407
static bool ParseName(State *state);
408
static bool ParseUnscopedName(State *state);
409
static bool ParseUnscopedTemplateName(State *state);
410
static bool ParseNestedName(State *state);
411
static bool ParsePrefix(State *state);
412
static bool ParseUnqualifiedName(State *state);
413
static bool ParseSourceName(State *state);
414
static bool ParseLocalSourceName(State *state);
415
static bool ParseNumber(State *state, int *number_out);
416
static bool ParseFloatNumber(State *state);
417
static bool ParseSeqId(State *state);
418
static bool ParseIdentifier(State *state, int length);
419
static bool ParseOperatorName(State *state);
420
static bool ParseSpecialName(State *state);
421
static bool ParseCallOffset(State *state);
422
static bool ParseNVOffset(State *state);
423
static bool ParseVOffset(State *state);
424
static bool ParseCtorDtorName(State *state);
425
static bool ParseType(State *state);
426
static bool ParseCVQualifiers(State *state);
427
static bool ParseBuiltinType(State *state);
428
static bool ParseFunctionType(State *state);
429
static bool ParseBareFunctionType(State *state);
430
static bool ParseClassEnumType(State *state);
431
static bool ParseArrayType(State *state);
432
static bool ParsePointerToMemberType(State *state);
433
static bool ParseTemplateParam(State *state);
434
static bool ParseTemplateTemplateParam(State *state);
435
static bool ParseTemplateArgs(State *state);
436
static bool ParseTemplateArg(State *state);
437
static bool ParseExpression(State *state);
438
static bool ParseExprPrimary(State *state);
439
static bool ParseLocalName(State *state);
440
static bool ParseDiscriminator(State *state);
441
static bool ParseSubstitution(State *state);
442
443
// Implementation note: the following code is a straightforward
444
// translation of the Itanium C++ ABI defined in BNF with a couple of
445
// exceptions.
446
//
447
// - Support GNU extensions not defined in the Itanium C++ ABI
448
// - <prefix> and <template-prefix> are combined to avoid infinite loop
449
// - Reorder patterns to shorten the code
450
// - Reorder patterns to give greedier functions precedence
451
//   We'll mark "Less greedy than" for these cases in the code
452
//
453
// Each parsing function changes the state and returns true on
454
// success.  Otherwise, don't change the state and returns false.  To
455
// ensure that the state isn't changed in the latter case, we save the
456
// original state before we call more than one parsing functions
457
// consecutively with &&, and restore the state if unsuccessful.  See
458
// ParseEncoding() as an example of this convention.  We follow the
459
// convention throughout the code.
460
//
461
// Originally we tried to do demangling without following the full ABI
462
// syntax but it turned out we needed to follow the full syntax to
463
// parse complicated cases like nested template arguments.  Note that
464
// implementing a full-fledged demangler isn't trivial (libiberty's
465
// cp-demangle.c has +4300 lines).
466
//
467
// Note that (foo) in <(foo) ...> is a modifier to be ignored.
468
//
469
// Reference:
470
// - Itanium C++ ABI
471
//   <http://www.codesourcery.com/cxx-abi/abi.html#mangling>
472
473
// <mangled-name> ::= _Z <encoding>
474
4.76k
static bool ParseMangledName(State *state) {
475
4.76k
  return ParseTwoCharToken(state, "_Z") && ParseEncoding(state);
476
4.76k
}
477
478
// <encoding> ::= <(function) name> <bare-function-type>
479
//            ::= <(data) name>
480
//            ::= <special-name>
481
3.53k
static bool ParseEncoding(State *state) {
482
3.53k
  State copy = *state;
483
3.53k
  if (ParseName(state) && ParseBareFunctionType(state)) {
484
3.53k
    return true;
485
3.53k
  }
486
0
  *state = copy;
487
488
0
  if (ParseName(state) || ParseSpecialName(state)) {
489
0
    return true;
490
0
  }
491
0
  return false;
492
0
}
493
494
// <name> ::= <nested-name>
495
//        ::= <unscoped-template-name> <template-args>
496
//        ::= <unscoped-name>
497
//        ::= <local-name>
498
15.9k
static bool ParseName(State *state) {
499
15.9k
  if (ParseNestedName(state) || ParseLocalName(state)) {
500
4.45k
    return true;
501
4.45k
  }
502
503
11.5k
  State copy = *state;
504
11.5k
  if (ParseUnscopedTemplateName(state) &&
505
7.07k
      ParseTemplateArgs(state)) {
506
0
    return true;
507
0
  }
508
11.5k
  *state = copy;
509
510
  // Less greedy than <unscoped-template-name> <template-args>.
511
11.5k
  if (ParseUnscopedName(state)) {
512
0
    return true;
513
0
  }
514
11.5k
  return false;
515
11.5k
}
516
517
// <unscoped-name> ::= <unqualified-name>
518
//                 ::= St <unqualified-name>
519
43.2k
static bool ParseUnscopedName(State *state) {
520
43.2k
  if (ParseUnqualifiedName(state)) {
521
14.8k
    return true;
522
14.8k
  }
523
524
28.4k
  State copy = *state;
525
28.4k
  if (ParseTwoCharToken(state, "St") &&
526
0
      MaybeAppend(state, "std::") &&
527
0
      ParseUnqualifiedName(state)) {
528
0
    return true;
529
0
  }
530
28.4k
  *state = copy;
531
28.4k
  return false;
532
28.4k
}
533
534
// <unscoped-template-name> ::= <unscoped-name>
535
//                          ::= <substitution>
536
11.5k
static bool ParseUnscopedTemplateName(State *state) {
537
11.5k
  return ParseUnscopedName(state) || ParseSubstitution(state);
538
11.5k
}
539
540
// <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
541
//               ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
542
15.9k
static bool ParseNestedName(State *state) {
543
15.9k
  State copy = *state;
544
15.9k
  if (ParseOneCharToken(state, 'N') &&
545
4.45k
      EnterNestedName(state) &&
546
4.45k
      Optional(ParseCVQualifiers(state)) &&
547
4.45k
      ParsePrefix(state) &&
548
4.45k
      LeaveNestedName(state, copy.nest_level) &&
549
4.45k
      ParseOneCharToken(state, 'E')) {
550
4.45k
    return true;
551
4.45k
  }
552
11.5k
  *state = copy;
553
11.5k
  return false;
554
15.9k
}
555
556
// This part is tricky.  If we literally translate them to code, we'll
557
// end up infinite loop.  Hence we merge them to avoid the case.
558
//
559
// <prefix> ::= <prefix> <unqualified-name>
560
//          ::= <template-prefix> <template-args>
561
//          ::= <template-param>
562
//          ::= <substitution>
563
//          ::= # empty
564
// <template-prefix> ::= <prefix> <(template) unqualified-name>
565
//                   ::= <template-param>
566
//                   ::= <substitution>
567
5.37k
static bool ParsePrefix(State *state) {
568
5.37k
  bool has_something = false;
569
24.6k
  while (true) {
570
24.6k
    MaybeAppendSeparator(state);
571
24.6k
    if (ParseTemplateParam(state) ||
572
24.6k
        ParseSubstitution(state) ||
573
20.1k
        ParseUnscopedName(state)) {
574
19.2k
      has_something = true;
575
19.2k
      MaybeIncreaseNestLevel(state);
576
19.2k
      continue;
577
19.2k
    }
578
5.37k
    MaybeCancelLastSeparator(state);
579
5.37k
    if (has_something && ParseTemplateArgs(state)) {
580
920
      return ParsePrefix(state);
581
4.45k
    } else {
582
4.45k
      break;
583
4.45k
    }
584
5.37k
  }
585
4.45k
  return true;
586
5.37k
}
587
588
// <unqualified-name> ::= <operator-name>
589
//                    ::= <ctor-dtor-name>
590
//                    ::= <source-name>
591
//                    ::= <local-source-name>
592
43.2k
static bool ParseUnqualifiedName(State *state) {
593
43.2k
  return (ParseOperatorName(state) ||
594
43.2k
          ParseCtorDtorName(state) ||
595
39.9k
          ParseSourceName(state) ||
596
28.4k
          ParseLocalSourceName(state));
597
43.2k
}
598
599
// <source-name> ::= <positive length number> <identifier>
600
39.9k
static bool ParseSourceName(State *state) {
601
39.9k
  State copy = *state;
602
39.9k
  int length = -1;
603
39.9k
  if (ParseNumber(state, &length) && ParseIdentifier(state, length)) {
604
11.5k
    return true;
605
11.5k
  }
606
28.4k
  *state = copy;
607
28.4k
  return false;
608
39.9k
}
609
610
// <local-source-name> ::= L <source-name> [<discriminator>]
611
//
612
// References:
613
//   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
614
//   http://gcc.gnu.org/viewcvs?view=rev&revision=124467
615
28.4k
static bool ParseLocalSourceName(State *state) {
616
28.4k
  State copy = *state;
617
28.4k
  if (ParseOneCharToken(state, 'L') && ParseSourceName(state) &&
618
0
      Optional(ParseDiscriminator(state))) {
619
0
    return true;
620
0
  }
621
28.4k
  *state = copy;
622
28.4k
  return false;
623
28.4k
}
624
625
// <number> ::= [n] <non-negative decimal integer>
626
// If "number_out" is non-null, then *number_out is set to the value of the
627
// parsed number on success.
628
39.9k
static bool ParseNumber(State *state, int *number_out) {
629
39.9k
  int sign = 1;
630
39.9k
  if (ParseOneCharToken(state, 'n')) {
631
0
    sign = -1;
632
0
  }
633
39.9k
  const char *p = state->mangled_cur;
634
39.9k
  int number = 0;
635
52.1k
  for (;*p != '\0'; ++p) {
636
45.0k
    if (IsDigit(*p)) {
637
12.2k
      number = number * 10 + (*p - '0');
638
32.8k
    } else {
639
32.8k
      break;
640
32.8k
    }
641
45.0k
  }
642
39.9k
  if (p != state->mangled_cur) {  // Conversion succeeded.
643
11.5k
    state->mangled_cur = p;
644
11.5k
    if (number_out != NULL) {
645
11.5k
      *number_out = number * sign;
646
11.5k
    }
647
11.5k
    return true;
648
11.5k
  }
649
28.4k
  return false;
650
39.9k
}
651
652
// Floating-point literals are encoded using a fixed-length lowercase
653
// hexadecimal string.
654
0
static bool ParseFloatNumber(State *state) {
655
0
  const char *p = state->mangled_cur;
656
0
  for (;*p != '\0'; ++p) {
657
0
    if (!IsDigit(*p) && !(*p >= 'a' && *p <= 'f')) {
658
0
      break;
659
0
    }
660
0
  }
661
0
  if (p != state->mangled_cur) {  // Conversion succeeded.
662
0
    state->mangled_cur = p;
663
0
    return true;
664
0
  }
665
0
  return false;
666
0
}
667
668
// The <seq-id> is a sequence number in base 36,
669
// using digits and upper case letters
670
17.6k
static bool ParseSeqId(State *state) {
671
17.6k
  const char *p = state->mangled_cur;
672
31.8k
  for (;*p != '\0'; ++p) {
673
31.8k
    if (!IsDigit(*p) && !(*p >= 'A' && *p <= 'Z')) {
674
17.6k
      break;
675
17.6k
    }
676
31.8k
  }
677
17.6k
  if (p != state->mangled_cur) {  // Conversion succeeded.
678
14.1k
    state->mangled_cur = p;
679
14.1k
    return true;
680
14.1k
  }
681
3.53k
  return false;
682
17.6k
}
683
684
// <identifier> ::= <unqualified source code identifier> (of given length)
685
11.5k
static bool ParseIdentifier(State *state, int length) {
686
11.5k
  if (length == -1 ||
687
11.5k
      !AtLeastNumCharsRemaining(state->mangled_cur, length)) {
688
0
    return false;
689
0
  }
690
11.5k
  if (IdentifierIsAnonymousNamespace(state, length)) {
691
0
    MaybeAppend(state, "(anonymous namespace)");
692
11.5k
  } else {
693
11.5k
    MaybeAppendWithLength(state, state->mangled_cur, length);
694
11.5k
  }
695
11.5k
  state->mangled_cur += length;
696
11.5k
  return true;
697
11.5k
}
698
699
// <operator-name> ::= nw, and other two letters cases
700
//                 ::= cv <type>  # (cast)
701
//                 ::= v  <digit> <source-name> # vendor extended operator
702
43.2k
static bool ParseOperatorName(State *state) {
703
43.2k
  if (!AtLeastNumCharsRemaining(state->mangled_cur, 2)) {
704
7.06k
    return false;
705
7.06k
  }
706
  // First check with "cv" (cast) case.
707
36.1k
  State copy = *state;
708
36.1k
  if (ParseTwoCharToken(state, "cv") &&
709
0
      MaybeAppend(state, "operator ") &&
710
0
      EnterNestedName(state) &&
711
0
      ParseType(state) &&
712
0
      LeaveNestedName(state, copy.nest_level)) {
713
0
    return true;
714
0
  }
715
36.1k
  *state = copy;
716
717
  // Then vendor extended operators.
718
36.1k
  if (ParseOneCharToken(state, 'v') && ParseCharClass(state, "0123456789") &&
719
0
      ParseSourceName(state)) {
720
0
    return true;
721
0
  }
722
36.1k
  *state = copy;
723
724
  // Other operator names should start with a lower alphabet followed
725
  // by a lower/upper alphabet.
726
36.1k
  if (!(IsLower(state->mangled_cur[0]) &&
727
36.1k
        IsAlpha(state->mangled_cur[1]))) {
728
36.1k
    return false;
729
36.1k
  }
730
  // We may want to perform a binary search if we really need speed.
731
0
  const AbbrevPair *p;
732
0
  for (p = kOperatorList; p->abbrev != NULL; ++p) {
733
0
    if (state->mangled_cur[0] == p->abbrev[0] &&
734
0
        state->mangled_cur[1] == p->abbrev[1]) {
735
0
      MaybeAppend(state, "operator");
736
0
      if (IsLower(*p->real_name)) {  // new, delete, etc.
737
0
        MaybeAppend(state, " ");
738
0
      }
739
0
      MaybeAppend(state, p->real_name);
740
0
      state->mangled_cur += 2;
741
0
      return true;
742
0
    }
743
0
  }
744
0
  return false;
745
0
}
746
747
// <special-name> ::= TV <type>
748
//                ::= TT <type>
749
//                ::= TI <type>
750
//                ::= TS <type>
751
//                ::= Tc <call-offset> <call-offset> <(base) encoding>
752
//                ::= GV <(object) name>
753
//                ::= T <call-offset> <(base) encoding>
754
// G++ extensions:
755
//                ::= TC <type> <(offset) number> _ <(base) type>
756
//                ::= TF <type>
757
//                ::= TJ <type>
758
//                ::= GR <name>
759
//                ::= GA <encoding>
760
//                ::= Th <call-offset> <(base) encoding>
761
//                ::= Tv <call-offset> <(base) encoding>
762
//
763
// Note: we don't care much about them since they don't appear in
764
// stack traces.  The are special data.
765
0
static bool ParseSpecialName(State *state) {
766
0
  State copy = *state;
767
0
  if (ParseOneCharToken(state, 'T') &&
768
0
      ParseCharClass(state, "VTIS") &&
769
0
      ParseType(state)) {
770
0
    return true;
771
0
  }
772
0
  *state = copy;
773
774
0
  if (ParseTwoCharToken(state, "Tc") && ParseCallOffset(state) &&
775
0
      ParseCallOffset(state) && ParseEncoding(state)) {
776
0
    return true;
777
0
  }
778
0
  *state = copy;
779
780
0
  if (ParseTwoCharToken(state, "GV") &&
781
0
      ParseName(state)) {
782
0
    return true;
783
0
  }
784
0
  *state = copy;
785
786
0
  if (ParseOneCharToken(state, 'T') && ParseCallOffset(state) &&
787
0
      ParseEncoding(state)) {
788
0
    return true;
789
0
  }
790
0
  *state = copy;
791
792
  // G++ extensions
793
0
  if (ParseTwoCharToken(state, "TC") && ParseType(state) &&
794
0
      ParseNumber(state, NULL) && ParseOneCharToken(state, '_') &&
795
0
      DisableAppend(state) &&
796
0
      ParseType(state)) {
797
0
    RestoreAppend(state, copy.append);
798
0
    return true;
799
0
  }
800
0
  *state = copy;
801
802
0
  if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "FJ") &&
803
0
      ParseType(state)) {
804
0
    return true;
805
0
  }
806
0
  *state = copy;
807
808
0
  if (ParseTwoCharToken(state, "GR") && ParseName(state)) {
809
0
    return true;
810
0
  }
811
0
  *state = copy;
812
813
0
  if (ParseTwoCharToken(state, "GA") && ParseEncoding(state)) {
814
0
    return true;
815
0
  }
816
0
  *state = copy;
817
818
0
  if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "hv") &&
819
0
      ParseCallOffset(state) && ParseEncoding(state)) {
820
0
    return true;
821
0
  }
822
0
  *state = copy;
823
0
  return false;
824
0
}
825
826
// <call-offset> ::= h <nv-offset> _
827
//               ::= v <v-offset> _
828
0
static bool ParseCallOffset(State *state) {
829
0
  State copy = *state;
830
0
  if (ParseOneCharToken(state, 'h') &&
831
0
      ParseNVOffset(state) && ParseOneCharToken(state, '_')) {
832
0
    return true;
833
0
  }
834
0
  *state = copy;
835
836
0
  if (ParseOneCharToken(state, 'v') &&
837
0
      ParseVOffset(state) && ParseOneCharToken(state, '_')) {
838
0
    return true;
839
0
  }
840
0
  *state = copy;
841
842
0
  return false;
843
0
}
844
845
// <nv-offset> ::= <(offset) number>
846
0
static bool ParseNVOffset(State *state) {
847
0
  return ParseNumber(state, NULL);
848
0
}
849
850
// <v-offset>  ::= <(offset) number> _ <(virtual offset) number>
851
0
static bool ParseVOffset(State *state) {
852
0
  State copy = *state;
853
0
  if (ParseNumber(state, NULL) && ParseOneCharToken(state, '_') &&
854
0
      ParseNumber(state, NULL)) {
855
0
    return true;
856
0
  }
857
0
  *state = copy;
858
0
  return false;
859
0
}
860
861
// <ctor-dtor-name> ::= C1 | C2 | C3
862
//                  ::= D0 | D1 | D2
863
43.2k
static bool ParseCtorDtorName(State *state) {
864
43.2k
  State copy = *state;
865
43.2k
  if (ParseOneCharToken(state, 'C') &&
866
3.30k
      ParseCharClass(state, "123")) {
867
3.30k
    const char * const prev_name = state->prev_name;
868
3.30k
    const int prev_name_length = state->prev_name_length;
869
3.30k
    MaybeAppendWithLength(state, prev_name, prev_name_length);
870
3.30k
    return true;
871
3.30k
  }
872
39.9k
  *state = copy;
873
874
39.9k
  if (ParseOneCharToken(state, 'D') &&
875
0
      ParseCharClass(state, "012")) {
876
0
    const char * const prev_name = state->prev_name;
877
0
    const int prev_name_length = state->prev_name_length;
878
0
    MaybeAppend(state, "~");
879
0
    MaybeAppendWithLength(state, prev_name, prev_name_length);
880
0
    return true;
881
0
  }
882
39.9k
  *state = copy;
883
39.9k
  return false;
884
39.9k
}
885
886
// <type> ::= <CV-qualifiers> <type>
887
//        ::= P <type>   # pointer-to
888
//        ::= R <type>   # reference-to
889
//        ::= O <type>   # rvalue reference-to (C++0x)
890
//        ::= C <type>   # complex pair (C 2000)
891
//        ::= G <type>   # imaginary (C 2000)
892
//        ::= U <source-name> <type>  # vendor extended type qualifier
893
//        ::= <builtin-type>
894
//        ::= <function-type>
895
//        ::= <class-enum-type>
896
//        ::= <array-type>
897
//        ::= <pointer-to-member-type>
898
//        ::= <template-template-param> <template-args>
899
//        ::= <template-param>
900
//        ::= <substitution>
901
//        ::= Dp <type>          # pack expansion of (C++0x)
902
//        ::= Dt <expression> E  # decltype of an id-expression or class
903
//                               # member access (C++0x)
904
//        ::= DT <expression> E  # decltype of an expression (C++0x)
905
//
906
25.6k
static bool ParseType(State *state) {
907
  // We should check CV-qualifers, and PRGC things first.
908
25.6k
  State copy = *state;
909
25.6k
  if (ParseCVQualifiers(state) && ParseType(state)) {
910
3.76k
    return true;
911
3.76k
  }
912
21.9k
  *state = copy;
913
914
21.9k
  if (ParseCharClass(state, "OPRCG") && ParseType(state)) {
915
4.10k
    return true;
916
4.10k
  }
917
17.8k
  *state = copy;
918
919
17.8k
  if (ParseTwoCharToken(state, "Dp") && ParseType(state)) {
920
0
    return true;
921
0
  }
922
17.8k
  *state = copy;
923
924
17.8k
  if (ParseOneCharToken(state, 'D') && ParseCharClass(state, "tT") &&
925
0
      ParseExpression(state) && ParseOneCharToken(state, 'E')) {
926
0
    return true;
927
0
  }
928
17.8k
  *state = copy;
929
930
17.8k
  if (ParseOneCharToken(state, 'U') && ParseSourceName(state) &&
931
0
      ParseType(state)) {
932
0
    return true;
933
0
  }
934
17.8k
  *state = copy;
935
936
17.8k
  if (ParseBuiltinType(state) ||
937
12.4k
      ParseFunctionType(state) ||
938
12.4k
      ParseClassEnumType(state) ||
939
11.5k
      ParseArrayType(state) ||
940
11.5k
      ParsePointerToMemberType(state) ||
941
13.3k
      ParseSubstitution(state)) {
942
13.3k
    return true;
943
13.3k
  }
944
945
4.45k
  if (ParseTemplateTemplateParam(state) &&
946
0
      ParseTemplateArgs(state)) {
947
0
    return true;
948
0
  }
949
4.45k
  *state = copy;
950
951
  // Less greedy than <template-template-param> <template-args>.
952
4.45k
  if (ParseTemplateParam(state)) {
953
0
    return true;
954
0
  }
955
956
4.45k
  return false;
957
4.45k
}
958
959
// <CV-qualifiers> ::= [r] [V] [K]
960
// We don't allow empty <CV-qualifiers> to avoid infinite loop in
961
// ParseType().
962
30.1k
static bool ParseCVQualifiers(State *state) {
963
30.1k
  int num_cv_qualifiers = 0;
964
30.1k
  num_cv_qualifiers += ParseOneCharToken(state, 'r');
965
30.1k
  num_cv_qualifiers += ParseOneCharToken(state, 'V');
966
30.1k
  num_cv_qualifiers += ParseOneCharToken(state, 'K');
967
30.1k
  return num_cv_qualifiers > 0;
968
30.1k
}
969
970
// <builtin-type> ::= v, etc.
971
//                ::= u <source-name>
972
17.8k
static bool ParseBuiltinType(State *state) {
973
17.8k
  const AbbrevPair *p;
974
313k
  for (p = kBuiltinTypeList; p->abbrev != NULL; ++p) {
975
300k
    if (state->mangled_cur[0] == p->abbrev[0]) {
976
5.37k
      MaybeAppend(state, p->real_name);
977
5.37k
      ++state->mangled_cur;
978
5.37k
      return true;
979
5.37k
    }
980
300k
  }
981
982
12.4k
  State copy = *state;
983
12.4k
  if (ParseOneCharToken(state, 'u') && ParseSourceName(state)) {
984
0
    return true;
985
0
  }
986
12.4k
  *state = copy;
987
12.4k
  return false;
988
12.4k
}
989
990
// <function-type> ::= F [Y] <bare-function-type> E
991
12.4k
static bool ParseFunctionType(State *state) {
992
12.4k
  State copy = *state;
993
12.4k
  if (ParseOneCharToken(state, 'F') &&
994
0
      Optional(ParseOneCharToken(state, 'Y')) &&
995
0
      ParseBareFunctionType(state) && ParseOneCharToken(state, 'E')) {
996
0
    return true;
997
0
  }
998
12.4k
  *state = copy;
999
12.4k
  return false;
1000
12.4k
}
1001
1002
// <bare-function-type> ::= <(signature) type>+
1003
3.53k
static bool ParseBareFunctionType(State *state) {
1004
3.53k
  State copy = *state;
1005
3.53k
  DisableAppend(state);
1006
3.53k
  if (OneOrMore(ParseType, state)) {
1007
3.53k
    RestoreAppend(state, copy.append);
1008
3.53k
    MaybeAppend(state, "()");
1009
3.53k
    return true;
1010
3.53k
  }
1011
0
  *state = copy;
1012
0
  return false;
1013
3.53k
}
1014
1015
// <class-enum-type> ::= <name>
1016
12.4k
static bool ParseClassEnumType(State *state) {
1017
12.4k
  return ParseName(state);
1018
12.4k
}
1019
1020
// <array-type> ::= A <(positive dimension) number> _ <(element) type>
1021
//              ::= A [<(dimension) expression>] _ <(element) type>
1022
11.5k
static bool ParseArrayType(State *state) {
1023
11.5k
  State copy = *state;
1024
11.5k
  if (ParseOneCharToken(state, 'A') && ParseNumber(state, NULL) &&
1025
0
      ParseOneCharToken(state, '_') && ParseType(state)) {
1026
0
    return true;
1027
0
  }
1028
11.5k
  *state = copy;
1029
1030
11.5k
  if (ParseOneCharToken(state, 'A') && Optional(ParseExpression(state)) &&
1031
0
      ParseOneCharToken(state, '_') && ParseType(state)) {
1032
0
    return true;
1033
0
  }
1034
11.5k
  *state = copy;
1035
11.5k
  return false;
1036
11.5k
}
1037
1038
// <pointer-to-member-type> ::= M <(class) type> <(member) type>
1039
11.5k
static bool ParsePointerToMemberType(State *state) {
1040
11.5k
  State copy = *state;
1041
11.5k
  if (ParseOneCharToken(state, 'M') && ParseType(state) &&
1042
0
      ParseType(state)) {
1043
0
    return true;
1044
0
  }
1045
11.5k
  *state = copy;
1046
11.5k
  return false;
1047
11.5k
}
1048
1049
// <template-param> ::= T_
1050
//                  ::= T <parameter-2 non-negative number> _
1051
33.5k
static bool ParseTemplateParam(State *state) {
1052
33.5k
  if (ParseTwoCharToken(state, "T_")) {
1053
0
    MaybeAppend(state, "?");  // We don't support template substitutions.
1054
0
    return true;
1055
0
  }
1056
1057
33.5k
  State copy = *state;
1058
33.5k
  if (ParseOneCharToken(state, 'T') && ParseNumber(state, NULL) &&
1059
0
      ParseOneCharToken(state, '_')) {
1060
0
    MaybeAppend(state, "?");  // We don't support template substitutions.
1061
0
    return true;
1062
0
  }
1063
33.5k
  *state = copy;
1064
33.5k
  return false;
1065
33.5k
}
1066
1067
1068
// <template-template-param> ::= <template-param>
1069
//                           ::= <substitution>
1070
4.45k
static bool ParseTemplateTemplateParam(State *state) {
1071
4.45k
  return (ParseTemplateParam(state) ||
1072
4.45k
          ParseSubstitution(state));
1073
4.45k
}
1074
1075
// <template-args> ::= I <template-arg>+ E
1076
11.7k
static bool ParseTemplateArgs(State *state) {
1077
11.7k
  State copy = *state;
1078
11.7k
  DisableAppend(state);
1079
11.7k
  if (ParseOneCharToken(state, 'I') &&
1080
920
      OneOrMore(ParseTemplateArg, state) &&
1081
920
      ParseOneCharToken(state, 'E')) {
1082
920
    RestoreAppend(state, copy.append);
1083
920
    MaybeAppend(state, "<>");
1084
920
    return true;
1085
920
  }
1086
10.8k
  *state = copy;
1087
10.8k
  return false;
1088
11.7k
}
1089
1090
// <template-arg>  ::= <type>
1091
//                 ::= <expr-primary>
1092
//                 ::= I <template-arg>* E        # argument pack
1093
//                 ::= X <expression> E
1094
2.30k
static bool ParseTemplateArg(State *state) {
1095
2.30k
  State copy = *state;
1096
2.30k
  if (ParseOneCharToken(state, 'I') &&
1097
0
      ZeroOrMore(ParseTemplateArg, state) &&
1098
0
      ParseOneCharToken(state, 'E')) {
1099
0
    return true;
1100
0
  }
1101
2.30k
  *state = copy;
1102
1103
2.30k
  if (ParseType(state) ||
1104
1.38k
      ParseExprPrimary(state)) {
1105
1.38k
    return true;
1106
1.38k
  }
1107
920
  *state = copy;
1108
1109
920
  if (ParseOneCharToken(state, 'X') && ParseExpression(state) &&
1110
0
      ParseOneCharToken(state, 'E')) {
1111
0
    return true;
1112
0
  }
1113
920
  *state = copy;
1114
920
  return false;
1115
920
}
1116
1117
// <expression> ::= <template-param>
1118
//              ::= <expr-primary>
1119
//              ::= <unary operator-name> <expression>
1120
//              ::= <binary operator-name> <expression> <expression>
1121
//              ::= <trinary operator-name> <expression> <expression>
1122
//                  <expression>
1123
//              ::= st <type>
1124
//              ::= sr <type> <unqualified-name> <template-args>
1125
//              ::= sr <type> <unqualified-name>
1126
0
static bool ParseExpression(State *state) {
1127
0
  if (ParseTemplateParam(state) || ParseExprPrimary(state)) {
1128
0
    return true;
1129
0
  }
1130
1131
0
  State copy = *state;
1132
0
  if (ParseOperatorName(state) &&
1133
0
      ParseExpression(state) &&
1134
0
      ParseExpression(state) &&
1135
0
      ParseExpression(state)) {
1136
0
    return true;
1137
0
  }
1138
0
  *state = copy;
1139
1140
0
  if (ParseOperatorName(state) &&
1141
0
      ParseExpression(state) &&
1142
0
      ParseExpression(state)) {
1143
0
    return true;
1144
0
  }
1145
0
  *state = copy;
1146
1147
0
  if (ParseOperatorName(state) &&
1148
0
      ParseExpression(state)) {
1149
0
    return true;
1150
0
  }
1151
0
  *state = copy;
1152
1153
0
  if (ParseTwoCharToken(state, "st") && ParseType(state)) {
1154
0
    return true;
1155
0
  }
1156
0
  *state = copy;
1157
1158
0
  if (ParseTwoCharToken(state, "sr") && ParseType(state) &&
1159
0
      ParseUnqualifiedName(state) &&
1160
0
      ParseTemplateArgs(state)) {
1161
0
    return true;
1162
0
  }
1163
0
  *state = copy;
1164
1165
0
  if (ParseTwoCharToken(state, "sr") && ParseType(state) &&
1166
0
      ParseUnqualifiedName(state)) {
1167
0
    return true;
1168
0
  }
1169
0
  *state = copy;
1170
0
  return false;
1171
0
}
1172
1173
// <expr-primary> ::= L <type> <(value) number> E
1174
//                ::= L <type> <(value) float> E
1175
//                ::= L <mangled-name> E
1176
//                // A bug in g++'s C++ ABI version 2 (-fabi-version=2).
1177
//                ::= LZ <encoding> E
1178
920
static bool ParseExprPrimary(State *state) {
1179
920
  State copy = *state;
1180
920
  if (ParseOneCharToken(state, 'L') && ParseType(state) &&
1181
0
      ParseNumber(state, NULL) &&
1182
0
      ParseOneCharToken(state, 'E')) {
1183
0
    return true;
1184
0
  }
1185
920
  *state = copy;
1186
1187
920
  if (ParseOneCharToken(state, 'L') && ParseType(state) &&
1188
0
      ParseFloatNumber(state) &&
1189
0
      ParseOneCharToken(state, 'E')) {
1190
0
    return true;
1191
0
  }
1192
920
  *state = copy;
1193
1194
920
  if (ParseOneCharToken(state, 'L') && ParseMangledName(state) &&
1195
0
      ParseOneCharToken(state, 'E')) {
1196
0
    return true;
1197
0
  }
1198
920
  *state = copy;
1199
1200
920
  if (ParseTwoCharToken(state, "LZ") && ParseEncoding(state) &&
1201
0
      ParseOneCharToken(state, 'E')) {
1202
0
    return true;
1203
0
  }
1204
920
  *state = copy;
1205
1206
920
  return false;
1207
920
}
1208
1209
// <local-name> := Z <(function) encoding> E <(entity) name>
1210
//                 [<discriminator>]
1211
//              := Z <(function) encoding> E s [<discriminator>]
1212
11.5k
static bool ParseLocalName(State *state) {
1213
11.5k
  State copy = *state;
1214
11.5k
  if (ParseOneCharToken(state, 'Z') && ParseEncoding(state) &&
1215
0
      ParseOneCharToken(state, 'E') && MaybeAppend(state, "::") &&
1216
0
      ParseName(state) && Optional(ParseDiscriminator(state))) {
1217
0
    return true;
1218
0
  }
1219
11.5k
  *state = copy;
1220
1221
11.5k
  if (ParseOneCharToken(state, 'Z') && ParseEncoding(state) &&
1222
0
      ParseTwoCharToken(state, "Es") && Optional(ParseDiscriminator(state))) {
1223
0
    return true;
1224
0
  }
1225
11.5k
  *state = copy;
1226
11.5k
  return false;
1227
11.5k
}
1228
1229
// <discriminator> := _ <(non-negative) number>
1230
0
static bool ParseDiscriminator(State *state) {
1231
0
  State copy = *state;
1232
0
  if (ParseOneCharToken(state, '_') && ParseNumber(state, NULL)) {
1233
0
    return true;
1234
0
  }
1235
0
  *state = copy;
1236
0
  return false;
1237
0
}
1238
1239
// <substitution> ::= S_
1240
//                ::= S <seq-id> _
1241
//                ::= St, etc.
1242
52.1k
static bool ParseSubstitution(State *state) {
1243
52.1k
  if (ParseTwoCharToken(state, "S_")) {
1244
920
    MaybeAppend(state, "?");  // We don't support substitutions.
1245
920
    return true;
1246
920
  }
1247
1248
51.2k
  State copy = *state;
1249
51.2k
  if (ParseOneCharToken(state, 'S') && ParseSeqId(state) &&
1250
14.1k
      ParseOneCharToken(state, '_')) {
1251
14.1k
    MaybeAppend(state, "?");  // We don't support substitutions.
1252
14.1k
    return true;
1253
14.1k
  }
1254
37.0k
  *state = copy;
1255
1256
  // Expand abbreviations like "St" => "std".
1257
37.0k
  if (ParseOneCharToken(state, 'S')) {
1258
3.53k
    const AbbrevPair *p;
1259
3.53k
    for (p = kSubstitutionList; p->abbrev != NULL; ++p) {
1260
3.53k
      if (state->mangled_cur[0] == p->abbrev[1]) {
1261
3.53k
        MaybeAppend(state, "std");
1262
3.53k
        if (p->real_name[0] != '\0') {
1263
0
          MaybeAppend(state, "::");
1264
0
          MaybeAppend(state, p->real_name);
1265
0
        }
1266
3.53k
        ++state->mangled_cur;
1267
3.53k
        return true;
1268
3.53k
      }
1269
3.53k
    }
1270
3.53k
  }
1271
33.5k
  *state = copy;
1272
33.5k
  return false;
1273
37.0k
}
1274
1275
// Parse <mangled-name>, optionally followed by either a function-clone suffix
1276
// or version suffix.  Returns true only if all of "mangled_cur" was consumed.
1277
4.76k
static bool ParseTopLevelMangledName(State *state) {
1278
4.76k
  if (ParseMangledName(state)) {
1279
3.53k
    if (state->mangled_cur[0] != '\0') {
1280
      // Drop trailing function clone suffix, if any.
1281
0
      if (IsFunctionCloneSuffix(state->mangled_cur)) {
1282
0
        return true;
1283
0
      }
1284
      // Append trailing version suffix if any.
1285
      // ex. _Z3foo@@GLIBCXX_3.4
1286
0
      if (state->mangled_cur[0] == '@') {
1287
0
        MaybeAppend(state, state->mangled_cur);
1288
0
        return true;
1289
0
      }
1290
0
      return false;  // Unconsumed suffix.
1291
0
    }
1292
3.53k
    return true;
1293
3.53k
  }
1294
1.23k
  return false;
1295
4.76k
}
1296
1297
// The demangler entry point.
1298
4.76k
bool Demangle(const char *mangled, char *out, int out_size) {
1299
4.76k
  State state;
1300
4.76k
  InitState(&state, mangled, out, out_size);
1301
4.76k
  return ParseTopLevelMangledName(&state) && !state.overflowed;
1302
4.76k
}
1303
1304
_END_GOOGLE_NAMESPACE_