// <special-name> ::= TV <type> // ::= TT <type> // ::= TI <type> // ::= TS <type> // ::= Tc <call-offset> <call-offset> <(base) encoding> // ::= GV <(object) name> // ::= T <call-offset> <(base) encoding> // G++ extensions: // ::= TC <type> <(offset) number> _ <(base) type> // ::= TF <type> // ::= TJ <type> // ::= GR <name> // ::= GA <encoding> // ::= Th <call-offset> <(base) encoding> // ::= Tv <call-offset> <(base) encoding> // // Note: we don't care much about them since they don't appear in // stack traces. The are special data. static bool ParseSpecialName(State *state) { State copy = *state; if (ParseChar(state, 'T') && ParseCharClass(state, "VTIS") && ParseType(state)) { return true; } *state = copy; if (ParseTwoChar(state, "Tc") && ParseCallOffset(state) && ParseCallOffset(state) && ParseEncoding(state)) { return true; } *state = copy; if (ParseTwoChar(state, "GV") && ParseName(state)) { return true; } *state = copy; if (ParseChar(state, 'T') && ParseCallOffset(state) && ParseEncoding(state)) { return true; } *state = copy; // G++ extensions if (ParseTwoChar(state, "TC") && ParseType(state) && ParseNumber(state) && ParseChar(state, '_') && DisableAppend(state) && ParseType(state)) { RestoreAppend(state, copy.append); return true; } *state = copy; if (ParseChar(state, 'T') && ParseCharClass(state, "FJ") && ParseType(state)) { return true; } *state = copy; if (ParseTwoChar(state, "GR") && ParseName(state)) { return true; } *state = copy; if (ParseTwoChar(state, "GA") && ParseEncoding(state)) { return true; } *state = copy; if (ParseChar(state, 'T') && ParseCharClass(state, "hv") && ParseCallOffset(state) && ParseEncoding(state)) { return true; } *state = copy; return false; }
// <type> ::= <CV-qualifiers> <type> // ::= P <type> # pointer-to // ::= R <type> # reference-to // ::= O <type> # rvalue reference-to (C++0x) // ::= C <type> # complex pair (C 2000) // ::= G <type> # imaginary (C 2000) // ::= U <source-name> <type> # vendor extended type qualifier // ::= <builtin-type> // ::= <function-type> // ::= <class-enum-type> // ::= <array-type> // ::= <pointer-to-member-type> // ::= <template-template-param> <template-args> // ::= <template-param> // ::= <substitution> // ::= Dp <type> # pack expansion of (C++0x) // ::= Dt <expression> E # decltype of an id-expression or class // # member access (C++0x) // ::= DT <expression> E # decltype of an expression (C++0x) // static bool ParseType(State *state) { // We should check CV-qualifers, and PRGC things first. State copy = *state; if (ParseCVQualifiers(state) && ParseType(state)) { return true; } *state = copy; if (ParseCharClass(state, "OPRCG") && ParseType(state)) { return true; } *state = copy; if (ParseTwoCharToken(state, "Dp") && ParseType(state)) { return true; } *state = copy; if (ParseOneCharToken(state, 'D') && ParseCharClass(state, "tT") && ParseExpression(state) && ParseOneCharToken(state, 'E')) { return true; } *state = copy; if (ParseOneCharToken(state, 'U') && ParseSourceName(state) && ParseType(state)) { return true; } *state = copy; if (ParseBuiltinType(state) || ParseFunctionType(state) || ParseClassEnumType(state) || ParseArrayType(state) || ParsePointerToMemberType(state) || ParseSubstitution(state)) { return true; } if (ParseTemplateTemplateParam(state) && ParseTemplateArgs(state)) { return true; } *state = copy; // Less greedy than <template-template-param> <template-args>. if (ParseTemplateParam(state)) { return true; } return false; }
// <ctor-dtor-name> ::= C1 | C2 | C3 // ::= D0 | D1 | D2 static bool ParseCtorDtorName(State *state) { State copy = *state; if (ParseChar(state, 'C') && ParseCharClass(state, "123")) { const char * const prev_name = state->prev_name; const int prev_name_length = state->prev_name_length; MaybeAppendWithLength(state, prev_name, prev_name_length); return true; } *state = copy; if (ParseChar(state, 'D') && ParseCharClass(state, "012")) { const char * const prev_name = state->prev_name; const int prev_name_length = state->prev_name_length; MaybeAppend(state, "~"); MaybeAppendWithLength(state, prev_name, prev_name_length); return true; } *state = copy; return false; }
// <operator-name> ::= nw, and other two letters cases // ::= cv <type> # (cast) // ::= v <digit> <source-name> # vendor extended operator static bool ParseOperatorName(State *state) { if (RemainingLength(state) < 2) { return false; } // First check with "cv" (cast) case. State copy = *state; if (ParseTwoChar(state, "cv") && MaybeAppend(state, "operator ") && EnterNestedName(state) && ParseType(state) && LeaveNestedName(state, copy.nest_level)) { return true; } *state = copy; // Then vendor extended operators. if (ParseChar(state, 'v') && ParseCharClass(state, "0123456789") && ParseSourceName(state)) { return true; } *state = copy; // Other operator names should start with a lower alphabet followed // by a lower/upper alphabet. if (!(IsLower(state->mangled_cur[0]) && IsAlpha(state->mangled_cur[1]))) { return false; } // We may want to perform a binary search if we really need speed. const AbbrevPair *p; for (p = kOperatorList; p->abbrev != nullptr; ++p) { if (state->mangled_cur[0] == p->abbrev[0] && state->mangled_cur[1] == p->abbrev[1]) { MaybeAppend(state, "operator"); if (IsLower(*p->real_name)) { // new, delete, etc. MaybeAppend(state, " "); } MaybeAppend(state, p->real_name); state->mangled_cur += 2; return true; } } return false; }