static bool ParseType()

in absl/debugging/internal/demangle.cc [1161:1233]


static bool ParseType(State *state) {
  ComplexityGuard guard(state);
  if (guard.IsTooComplex()) return false;
  ParseState copy = state->parse_state;

  // We should check CV-qualifers, and PRGC things first.
  //
  // CV-qualifiers overlap with some operator names, but an operator name is not
  // valid as a type.  To avoid an ambiguity that can lead to exponential time
  // complexity, refuse to backtrack the CV-qualifiers.
  //
  // _Z4aoeuIrMvvE
  //  => _Z 4aoeuI        rM  v     v   E
  //         aoeu<operator%=, void, void>
  //  => _Z 4aoeuI r Mv v              E
  //         aoeu<void void::* restrict>
  //
  // By consuming the CV-qualifiers first, the former parse is disabled.
  if (ParseCVQualifiers(state)) {
    const bool result = ParseType(state);
    if (!result) state->parse_state = copy;
    return result;
  }
  state->parse_state = copy;

  // Similarly, these tag characters can overlap with other <name>s resulting in
  // two different parse prefixes that land on <template-args> in the same
  // place, such as "C3r1xI...".  So, disable the "ctor-name = C3" parse by
  // refusing to backtrack the tag characters.
  if (ParseCharClass(state, "OPRCG")) {
    const bool result = ParseType(state);
    if (!result) state->parse_state = copy;
    return result;
  }
  state->parse_state = copy;

  if (ParseTwoCharToken(state, "Dp") && ParseType(state)) {
    return true;
  }
  state->parse_state = copy;

  if (ParseOneCharToken(state, 'U') && ParseSourceName(state) &&
      ParseType(state)) {
    return true;
  }
  state->parse_state = copy;

  if (ParseBuiltinType(state) || ParseFunctionType(state) ||
      ParseClassEnumType(state) || ParseArrayType(state) ||
      ParsePointerToMemberType(state) || ParseDecltype(state) ||
      // "std" on its own isn't a type.
      ParseSubstitution(state, /*accept_std=*/false)) {
    return true;
  }

  if (ParseTemplateTemplateParam(state) && ParseTemplateArgs(state)) {
    return true;
  }
  state->parse_state = copy;

  // Less greedy than <template-template-param> <template-args>.
  if (ParseTemplateParam(state)) {
    return true;
  }

  if (ParseTwoCharToken(state, "Dv") && ParseNumber(state, nullptr) &&
      ParseOneCharToken(state, '_')) {
    return true;
  }
  state->parse_state = copy;

  return false;
}