From 4352d7221c89a213aea77086bef214cd810ea43e Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Tue, 6 Mar 2018 14:21:08 +0000 Subject: [PATCH] [demangler] Modernize parse_unresolved_name. llvm-svn: 326796 --- libcxxabi/src/cxa_demangle.cpp | 580 +++++++++++++---------------------------- 1 file changed, 177 insertions(+), 403 deletions(-) diff --git a/libcxxabi/src/cxa_demangle.cpp b/libcxxabi/src/cxa_demangle.cpp index eca66e3..51952bd 100644 --- a/libcxxabi/src/cxa_demangle.cpp +++ b/libcxxabi/src/cxa_demangle.cpp @@ -2102,6 +2102,13 @@ struct Db { Node *parseAbiTags(Node *N); + /// Parse the production. + Node *parseUnresolvedName(); + Node *parseSimpleId(); + Node *parseBaseUnresolvedName(); + Node *parseUnresolvedType(); + Node *parseDestructorName(); + // FIXME: remove this when all the parse_* functions have been rewritten. template Node *legacyParse() { @@ -2147,46 +2154,6 @@ const char *parse_type(const char *first, const char *last, Db &db) { return db.First; } -const char *parse_decltype(const char *first, const char *last, Db &db) { - db.First = first; - db.Last = last; - Node *R = db.parseDecltype(); - if (R == nullptr) - return first; - db.Names.push_back(R); - return db.First; -} - -const char *parse_source_name(const char *first, const char *last, Db &db) { - db.First = first; - db.Last = last; - Node *R = db.parseSourceName(/*NameState=*/nullptr); - if (R == nullptr) - return first; - db.Names.push_back(R); - return db.First; -} - -const char *parse_operator_name(const char *first, const char *last, Db &db) { - db.First = first; - db.Last = last; - Node *R = db.parseOperatorName(/*NameState=*/nullptr); - if (R == nullptr) - return first; - db.Names.push_back(R); - return db.First; -} - -const char *parse_unqualified_name(const char *first, const char *last, Db &db) { - db.First = first; - db.Last = last; - Node *R = db.parseUnqualifiedName(/*NameState=*/nullptr); - if (R == nullptr) - return first; - db.Names.push_back(R); - return db.First; -} - const char *parse_encoding(const char *first, const char *last, Db &db) { db.First = first; db.Last = last; @@ -2200,7 +2167,6 @@ const char *parse_encoding(const char *first, const char *last, Db &db) { const char* parse_discriminator(const char* first, const char* last); const char *parse_template_args(const char *first, const char *last, Db &db); const char *parse_template_param(const char *, const char *, Db &); -const char *parse_unresolved_name(const char *, const char *, Db &); const char *parse_substitution(const char *, const char *, Db &); @@ -2797,6 +2763,172 @@ Node *Db::parseNestedName(NameState *State) { return SoFar; } +// ::= [ ] +Node *Db::parseSimpleId() { + Node *SN = parseSourceName(/*NameState=*/nullptr); + if (SN == nullptr) + return nullptr; + if (look() == 'I') { + Node *TA = legacyParse(); + if (TA == nullptr) + return nullptr; + return make(SN, TA); + } + return SN; +} + +// ::= # e.g., ~T or ~decltype(f()) +// ::= # e.g., ~A<2*N> +Node *Db::parseDestructorName() { + Node *Result; + if (std::isdigit(look())) + Result = parseSimpleId(); + else + Result = parseUnresolvedType(); + if (Result == nullptr) + return nullptr; + return make(Result); +} + +// ::= +// ::= +// ::= +Node *Db::parseUnresolvedType() { + if (look() == 'T') { + Node *TP = legacyParse(); + if (TP == nullptr) + return nullptr; + Subs.push_back(TP); + return TP; + } + if (look() == 'D') { + Node *DT = parseDecltype(); + if (DT == nullptr) + return nullptr; + Subs.push_back(DT); + return DT; + } + return legacyParse(); +} + +// ::= # unresolved name +// extension ::= # unresolved operator-function-id +// extension ::= # unresolved operator template-id +// ::= on # unresolved operator-function-id +// ::= on # unresolved operator template-id +// ::= dn # destructor or pseudo-destructor; +// # e.g. ~X or ~X +Node *Db::parseBaseUnresolvedName() { + if (std::isdigit(look())) + return parseSimpleId(); + + if (consumeIf("dn")) + return parseDestructorName(); + + consumeIf("on"); + + Node *Oper = parseOperatorName(/*NameState=*/nullptr); + if (Oper == nullptr) + return nullptr; + if (look() == 'I') { + Node *TA = legacyParse(); + if (TA == nullptr) + return nullptr; + return make(Oper, TA); + } + return Oper; +} + +// +// extension ::= srN [] * E +// ::= [gs] # x or (with "gs") ::x +// ::= [gs] sr + E +// # A::x, N::y, A::z; "gs" means leading "::" +// ::= sr # T::x / decltype(p)::x +// extension ::= sr +// # T::N::x /decltype(p)::N::x +// (ignored) ::= srN + E +// +// ::= +Node *Db::parseUnresolvedName() { + Node *SoFar = nullptr; + + // srN [] * E + // srN + E + if (consumeIf("srN")) { + SoFar = parseUnresolvedType(); + if (SoFar == nullptr) + return nullptr; + + if (look() == 'I') { + Node *TA = legacyParse(); + if (TA == nullptr) + return nullptr; + SoFar = make(SoFar, TA); + } + + while (!consumeIf('E')) { + Node *Qual = parseSimpleId(); + if (Qual == nullptr) + return nullptr; + SoFar = make(SoFar, Qual); + } + + Node *Base = parseBaseUnresolvedName(); + if (Base == nullptr) + return nullptr; + return make(SoFar, Base); + } + + bool Global = consumeIf("gs"); + + // [gs] # x or (with "gs") ::x + if (!consumeIf("sr")) { + SoFar = parseBaseUnresolvedName(); + if (SoFar == nullptr) + return nullptr; + if (Global) + SoFar = make(SoFar); + return SoFar; + } + + // [gs] sr + E + if (std::isdigit(look())) { + do { + Node *Qual = parseSimpleId(); + if (Qual == nullptr) + return nullptr; + if (SoFar) + SoFar = make(SoFar, Qual); + else if (Global) + SoFar = make(Qual); + else + SoFar = Qual; + } while (!consumeIf('E')); + } + // sr + // sr + else { + SoFar = parseUnresolvedType(); + if (SoFar == nullptr) + return nullptr; + + if (look() == 'I') { + Node *TA = legacyParse(); + if (TA == nullptr) + return nullptr; + SoFar = make(SoFar, TA); + } + } + + assert(SoFar != nullptr); + + Node *Base = parseBaseUnresolvedName(); + if (Base == nullptr) + return nullptr; + return make(SoFar, Base); +} + // ::= [] // ::= B Node *Db::parseAbiTags(Node *N) { @@ -3844,7 +3976,7 @@ Node *Db::parseExpr() { return make(E, Global, /*is_array=*/false); } case 'n': - return legacyParse(); + return parseUnresolvedName(); case 's': { First += 2; Node *LHS = parseExpr(); @@ -3986,7 +4118,7 @@ Node *Db::parseExpr() { case 'o': switch (First[1]) { case 'n': - return legacyParse(); + return parseUnresolvedName(); case 'o': First += 2; return parseBinaryExpr("||"); @@ -4094,7 +4226,7 @@ Node *Db::parseExpr() { return make(Child); } case 'r': - return legacyParse(); + return parseUnresolvedName(); case 't': { First += 2; Node *Ty = parseType(); @@ -4176,7 +4308,7 @@ Node *Db::parseExpr() { case '7': case '8': case '9': - return legacyParse(); + return parseUnresolvedName(); } return nullptr; } @@ -4583,364 +4715,6 @@ parse_template_param(const char* first, const char* last, Db& db) return first; } -// ::= [ ] - -const char* -parse_simple_id(const char* first, const char* last, Db& db) -{ - if (first != last) - { - const char* t = parse_source_name(first, last, db); - if (t != first) - { - const char* t1 = parse_template_args(t, last, db); - if (t1 != t) - { - if (db.Names.size() < 2) - return first; - auto args = db.Names.back(); - db.Names.pop_back(); - db.Names.back() = - db.make(db.Names.back(), args); - } - first = t1; - } - else - first = t; - } - return first; -} - -// ::= -// ::= -// ::= - -const char* -parse_unresolved_type(const char* first, const char* last, Db& db) -{ - if (first != last) - { - const char* t = first; - switch (*first) - { - case 'T': - { - size_t k0 = db.Names.size(); - t = parse_template_param(first, last, db); - size_t k1 = db.Names.size(); - if (t != first && k1 == k0 + 1) - { - db.Subs.push_back(db.Names.back()); - first = t; - } - else - { - for (; k1 != k0; --k1) - db.Names.pop_back(); - } - break; - } - case 'D': - t = parse_decltype(first, last, db); - if (t != first) - { - if (db.Names.empty()) - return first; - db.Subs.push_back(db.Names.back()); - first = t; - } - break; - case 'S': - t = parse_substitution(first, last, db); - if (t != first) - first = t; - else - { - if (last - first > 2 && first[1] == 't') - { - t = parse_unqualified_name(first+2, last, db); - if (t != first+2) - { - if (db.Names.empty()) - return first; - db.Names.back() = - db.make(db.Names.back()); - db.Subs.push_back(db.Names.back()); - first = t; - } - } - } - break; - } - } - return first; -} - -// ::= # e.g., ~T or ~decltype(f()) -// ::= # e.g., ~A<2*N> - -const char* -parse_destructor_name(const char* first, const char* last, Db& db) -{ - if (first != last) - { - const char* t = parse_unresolved_type(first, last, db); - if (t == first) - t = parse_simple_id(first, last, db); - if (t != first) - { - if (db.Names.empty()) - return first; - db.Names.back() = db.make(db.Names.back()); - first = t; - } - } - return first; -} - -// ::= # unresolved name -// extension ::= # unresolved operator-function-id -// extension ::= # unresolved operator template-id -// ::= on # unresolved operator-function-id -// ::= on # unresolved operator template-id -// ::= dn # destructor or pseudo-destructor; -// # e.g. ~X or ~X - -const char* -parse_base_unresolved_name(const char* first, const char* last, Db& db) -{ - if (last - first >= 2) - { - if ((first[0] == 'o' || first[0] == 'd') && first[1] == 'n') - { - if (first[0] == 'o') - { - const char* t = parse_operator_name(first+2, last, db); - if (t != first+2) - { - first = parse_template_args(t, last, db); - if (first != t) - { - if (db.Names.size() < 2) - return first; - auto args = db.Names.back(); - db.Names.pop_back(); - db.Names.back() = - db.make( - db.Names.back(), args); - } - } - } - else - { - const char* t = parse_destructor_name(first+2, last, db); - if (t != first+2) - first = t; - } - } - else - { - const char* t = parse_simple_id(first, last, db); - if (t == first) - { - t = parse_operator_name(first, last, db); - if (t != first) - { - first = parse_template_args(t, last, db); - if (first != t) - { - if (db.Names.size() < 2) - return first; - auto args = db.Names.back(); - db.Names.pop_back(); - db.Names.back() = - db.make( - db.Names.back(), args); - } - } - } - else - first = t; - } - } - return first; -} - -// ::= - -const char* -parse_unresolved_qualifier_level(const char* first, const char* last, Db& db) -{ - return parse_simple_id(first, last, db); -} - -// -// extension ::= srN [] * E -// ::= [gs] # x or (with "gs") ::x -// ::= [gs] sr + E -// # A::x, N::y, A::z; "gs" means leading "::" -// ::= sr # T::x / decltype(p)::x -// extension ::= sr -// # T::N::x /decltype(p)::N::x -// (ignored) ::= srN + E - -const char* -parse_unresolved_name(const char* first, const char* last, Db& db) -{ - if (last - first > 2) - { - const char* t = first; - bool global = false; - if (t[0] == 'g' && t[1] == 's') - { - global = true; - t += 2; - } - const char* t2 = parse_base_unresolved_name(t, last, db); - if (t2 != t) - { - if (global) - { - if (db.Names.empty()) - return first; - db.Names.back() = - db.make(db.Names.back()); - } - first = t2; - } - else if (last - t > 2 && t[0] == 's' && t[1] == 'r') - { - if (t[2] == 'N') - { - t += 3; - const char* t1 = parse_unresolved_type(t, last, db); - if (t1 == t || t1 == last) - return first; - t = t1; - t1 = parse_template_args(t, last, db); - if (t1 != t) - { - if (db.Names.size() < 2) - return first; - auto args = db.Names.back(); - db.Names.pop_back(); - db.Names.back() = db.make( - db.Names.back(), args); - t = t1; - if (t == last) - { - db.Names.pop_back(); - return first; - } - } - while (*t != 'E') - { - t1 = parse_unresolved_qualifier_level(t, last, db); - if (t1 == t || t1 == last || db.Names.size() < 2) - return first; - auto s = db.Names.back(); - db.Names.pop_back(); - db.Names.back() = - db.make(db.Names.back(), s); - t = t1; - } - ++t; - t1 = parse_base_unresolved_name(t, last, db); - if (t1 == t) - { - if (!db.Names.empty()) - db.Names.pop_back(); - return first; - } - if (db.Names.size() < 2) - return first; - auto s = db.Names.back(); - db.Names.pop_back(); - db.Names.back() = - db.make(db.Names.back(), s); - first = t1; - } - else - { - t += 2; - const char* t1 = parse_unresolved_type(t, last, db); - if (t1 != t) - { - t = t1; - t1 = parse_template_args(t, last, db); - if (t1 != t) - { - if (db.Names.size() < 2) - return first; - auto args = db.Names.back(); - db.Names.pop_back(); - db.Names.back() = - db.make( - db.Names.back(), args); - t = t1; - } - t1 = parse_base_unresolved_name(t, last, db); - if (t1 == t) - { - if (!db.Names.empty()) - db.Names.pop_back(); - return first; - } - if (db.Names.size() < 2) - return first; - auto s = db.Names.back(); - db.Names.pop_back(); - db.Names.back() = - db.make(db.Names.back(), s); - first = t1; - } - else - { - t1 = parse_unresolved_qualifier_level(t, last, db); - if (t1 == t || t1 == last) - return first; - t = t1; - if (global) - { - if (db.Names.empty()) - return first; - db.Names.back() = - db.make( - db.Names.back()); - } - while (*t != 'E') - { - t1 = parse_unresolved_qualifier_level(t, last, db); - if (t1 == t || t1 == last || db.Names.size() < 2) - return first; - auto s = db.Names.back(); - db.Names.pop_back(); - db.Names.back() = db.make( - db.Names.back(), s); - t = t1; - } - ++t; - t1 = parse_base_unresolved_name(t, last, db); - if (t1 == t) - { - if (!db.Names.empty()) - db.Names.pop_back(); - return first; - } - if (db.Names.size() < 2) - return first; - auto s = db.Names.back(); - db.Names.pop_back(); - db.Names.back() = - db.make(db.Names.back(), s); - first = t1; - } - } - } - } - return first; -} - // ::= # type or template // ::= X E # expression // ::= # simple expressions -- 2.7.4