in absl/debugging/internal/demangle.cc [1636:1741]
static bool ParseExpression(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
if (ParseTemplateParam(state) || ParseExprPrimary(state)) {
return true;
}
ParseState copy = state->parse_state;
// Object/function call expression.
if (ParseTwoCharToken(state, "cl") && OneOrMore(ParseExpression, state) &&
ParseOneCharToken(state, 'E')) {
return true;
}
state->parse_state = copy;
// Clang-specific "cp <simple-id> <expression>* E"
// https://clang.llvm.org/doxygen/ItaniumMangle_8cpp_source.html#l04338
if (ParseTwoCharToken(state, "cp") && ParseSimpleId(state) &&
ZeroOrMore(ParseExpression, state) && ParseOneCharToken(state, 'E')) {
return true;
}
state->parse_state = copy;
// Function-param expression (level 0).
if (ParseTwoCharToken(state, "fp") && Optional(ParseCVQualifiers(state)) &&
Optional(ParseNumber(state, nullptr)) && ParseOneCharToken(state, '_')) {
return true;
}
state->parse_state = copy;
// Function-param expression (level 1+).
if (ParseTwoCharToken(state, "fL") && Optional(ParseNumber(state, nullptr)) &&
ParseOneCharToken(state, 'p') && Optional(ParseCVQualifiers(state)) &&
Optional(ParseNumber(state, nullptr)) && ParseOneCharToken(state, '_')) {
return true;
}
state->parse_state = copy;
// Parse the conversion expressions jointly to avoid re-parsing the <type> in
// their common prefix. Parsed as:
// <expression> ::= cv <type> <conversion-args>
// <conversion-args> ::= _ <expression>* E
// ::= <expression>
//
// Also don't try ParseOperatorName after seeing "cv", since ParseOperatorName
// also needs to accept "cv <type>" in other contexts.
if (ParseTwoCharToken(state, "cv")) {
if (ParseType(state)) {
ParseState copy2 = state->parse_state;
if (ParseOneCharToken(state, '_') && ZeroOrMore(ParseExpression, state) &&
ParseOneCharToken(state, 'E')) {
return true;
}
state->parse_state = copy2;
if (ParseExpression(state)) {
return true;
}
}
} else {
// Parse unary, binary, and ternary operator expressions jointly, taking
// care not to re-parse subexpressions repeatedly. Parse like:
// <expression> ::= <operator-name> <expression>
// [<one-to-two-expressions>]
// <one-to-two-expressions> ::= <expression> [<expression>]
int arity = -1;
if (ParseOperatorName(state, &arity) &&
arity > 0 && // 0 arity => disabled.
(arity < 3 || ParseExpression(state)) &&
(arity < 2 || ParseExpression(state)) &&
(arity < 1 || ParseExpression(state))) {
return true;
}
}
state->parse_state = copy;
// sizeof type
if (ParseTwoCharToken(state, "st") && ParseType(state)) {
return true;
}
state->parse_state = copy;
// Object and pointer member access expressions.
if ((ParseTwoCharToken(state, "dt") || ParseTwoCharToken(state, "pt")) &&
ParseExpression(state) && ParseType(state)) {
return true;
}
state->parse_state = copy;
// Pointer-to-member access expressions. This parses the same as a binary
// operator, but it's implemented separately because "ds" shouldn't be
// accepted in other contexts that parse an operator name.
if (ParseTwoCharToken(state, "ds") && ParseExpression(state) &&
ParseExpression(state)) {
return true;
}
state->parse_state = copy;
// Parameter pack expansion
if (ParseTwoCharToken(state, "sp") && ParseExpression(state)) {
return true;
}
state->parse_state = copy;
return ParseUnresolvedName(state);
}