Thanks for the quick fix! On Tue, Mar 6, 2018 at 11:32 PM, Erik Pilkington <erik.pilking...@gmail.com> wrote:
> No, that was a mistake, fixed in r326871. Thanks for pointing this out! > Erik > > > On 2018-03-06 11:10 PM, Nico Weber wrote: > > Hi Erik, > > before this change, ___Z10blocksNRVOv_block_invoke demangled to > 'invocation function for block in blocksNRVO()', now it's no longer > demangled. Was that an intentional change? > > On Tue, Mar 6, 2018 at 9:21 AM, Erik Pilkington via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > >> Author: epilk >> Date: Tue Mar 6 06:21:10 2018 >> New Revision: 326797 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=326797&view=rev >> Log: >> [demangler] Modernize the rest of the demangler. >> >> Modified: >> libcxxabi/trunk/src/cxa_demangle.cpp >> libcxxabi/trunk/test/test_demangle.pass.cpp >> >> Modified: libcxxabi/trunk/src/cxa_demangle.cpp >> URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_ >> demangle.cpp?rev=326797&r1=326796&r2=326797&view=diff >> ============================================================ >> ================== >> --- libcxxabi/trunk/src/cxa_demangle.cpp (original) >> +++ libcxxabi/trunk/src/cxa_demangle.cpp Tue Mar 6 06:21:10 2018 >> @@ -2002,6 +2002,8 @@ struct Db { >> >> BumpPointerAllocator ASTAllocator; >> >> + Db(const char *First_, const char *Last_) : First(First_), Last(Last_) >> {} >> + >> template <class T, class... Args> T *make(Args &&... args) { >> return new (ASTAllocator.allocate(sizeof(T))) >> T(std::forward<Args>(args)...); >> @@ -2054,6 +2056,12 @@ struct Db { >> bool parsePositiveInteger(size_t *Out); >> StringView parseBareSourceName(); >> >> + bool parseSeqId(size_t *Out); >> + Node *parseSubstitution(); >> + Node *parseTemplateParam(); >> + Node *parseTemplateArgs(); >> + Node *parseTemplateArg(); >> + >> /// Parse the <expr> production. >> Node *parseExpr(); >> Node *parsePrefixExpr(StringView Kind); >> @@ -2109,66 +2117,11 @@ struct Db { >> Node *parseUnresolvedType(); >> Node *parseDestructorName(); >> >> - // FIXME: remove this when all the parse_* functions have been >> rewritten. >> - template <const char *(*parse_fn)(const char *, const char *, Db &)> >> - Node *legacyParse() { >> - size_t BeforeType = Names.size(); >> - const char *OrigFirst = First; >> - const char *T = parse_fn(First, Last, *this); >> - if (T == OrigFirst || BeforeType + 1 != Names.size()) >> - return nullptr; >> - First = T; >> - Node *R = Names.back(); >> - Names.pop_back(); >> - return R; >> - } >> + /// Top-level entry point into the parser. >> + Node *parse(); >> }; >> >> -const char *parse_expression(const char *first, const char *last, Db >> &db) { >> - db.First = first; >> - db.Last = last; >> - Node *R = db.parseExpr(); >> - if (R == nullptr) >> - return first; >> - db.Names.push_back(R); >> - return db.First; >> -} >> - >> -const char *parse_expr_primary(const char *first, const char *last, Db >> &db) { >> - db.First = first; >> - db.Last = last; >> - Node *R = db.parseExprPrimary(); >> - if (R == nullptr) >> - return first; >> - db.Names.push_back(R); >> - return db.First; >> -} >> - >> -const char *parse_type(const char *first, const char *last, Db &db) { >> - db.First = first; >> - db.Last = last; >> - Node *R = db.parseType(); >> - 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; >> - Node *R = db.parseEncoding(); >> - if (R == nullptr) >> - return first; >> - db.Names.push_back(R); >> - return db.First; >> -} >> - >> 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_substitution(const char *, const char *, Db &); >> - >> >> // <name> ::= <nested-name> // N >> // ::= <local-name> # See Scope Encoding below // Z >> @@ -2187,10 +2140,12 @@ Node *Db::parseName(NameState *State) { >> >> // ::= <unscoped-template-name> <template-args> >> if (look() == 'S' && look(1) != 't') { >> - Node *S = legacyParse<parse_substitution>(); >> + Node *S = parseSubstitution(); >> + if (S == nullptr) >> + return nullptr; >> if (look() != 'I') >> return nullptr; >> - Node *TA = legacyParse<parse_template_args>(); >> + Node *TA = parseTemplateArgs(); >> if (TA == nullptr) >> return nullptr; >> if (State) State->EndsWithTemplateArgs = true; >> @@ -2203,7 +2158,7 @@ Node *Db::parseName(NameState *State) { >> // ::= <unscoped-template-name> <template-args> >> if (look() == 'I') { >> Subs.push_back(N); >> - Node *TA = legacyParse<parse_template_args>(); >> + Node *TA = parseTemplateArgs(); >> if (TA == nullptr) >> return nullptr; >> if (State) State->EndsWithTemplateArgs = true; >> @@ -2693,7 +2648,7 @@ Node *Db::parseNestedName(NameState *Sta >> >> // ::= <template-param> >> if (look() == 'T') { >> - Node *TP = legacyParse<parse_template_param>(); >> + Node *TP = parseTemplateParam(); >> if (TP == nullptr) >> return nullptr; >> PushComponent(TP); >> @@ -2703,7 +2658,7 @@ Node *Db::parseNestedName(NameState *Sta >> >> // ::= <template-prefix> <template-args> >> if (look() == 'I') { >> - Node *TA = legacyParse<parse_template_args>(); >> + Node *TA = parseTemplateArgs(); >> if (TA == nullptr || SoFar == nullptr) >> return nullptr; >> SoFar = make<NameWithTemplateArgs>(SoFar, TA); >> @@ -2724,7 +2679,7 @@ Node *Db::parseNestedName(NameState *Sta >> >> // ::= <substitution> >> if (look() == 'S' && look(1) != 't') { >> - Node *S = legacyParse<parse_substitution>(); >> + Node *S = parseSubstitution(); >> if (S == nullptr) >> return nullptr; >> PushComponent(S); >> @@ -2769,7 +2724,7 @@ Node *Db::parseSimpleId() { >> if (SN == nullptr) >> return nullptr; >> if (look() == 'I') { >> - Node *TA = legacyParse<parse_template_args>(); >> + Node *TA = parseTemplateArgs(); >> if (TA == nullptr) >> return nullptr; >> return make<NameWithTemplateArgs>(SN, TA); >> @@ -2795,7 +2750,7 @@ Node *Db::parseDestructorName() { >> // ::= <substitution> >> Node *Db::parseUnresolvedType() { >> if (look() == 'T') { >> - Node *TP = legacyParse<parse_template_param>(); >> + Node *TP = parseTemplateParam(); >> if (TP == nullptr) >> return nullptr; >> Subs.push_back(TP); >> @@ -2808,7 +2763,7 @@ Node *Db::parseUnresolvedType() { >> Subs.push_back(DT); >> return DT; >> } >> - return legacyParse<parse_substitution>(); >> + return parseSubstitution(); >> } >> >> // <base-unresolved-name> ::= <simple-id> >> # unresolved name >> @@ -2831,7 +2786,7 @@ Node *Db::parseBaseUnresolvedName() { >> if (Oper == nullptr) >> return nullptr; >> if (look() == 'I') { >> - Node *TA = legacyParse<parse_template_args>(); >> + Node *TA = parseTemplateArgs(); >> if (TA == nullptr) >> return nullptr; >> return make<NameWithTemplateArgs>(Oper, TA); >> @@ -2861,7 +2816,7 @@ Node *Db::parseUnresolvedName() { >> return nullptr; >> >> if (look() == 'I') { >> - Node *TA = legacyParse<parse_template_args>(); >> + Node *TA = parseTemplateArgs(); >> if (TA == nullptr) >> return nullptr; >> SoFar = make<NameWithTemplateArgs>(SoFar, TA); >> @@ -2914,7 +2869,7 @@ Node *Db::parseUnresolvedName() { >> return nullptr; >> >> if (look() == 'I') { >> - Node *TA = legacyParse<parse_template_args>(); >> + Node *TA = parseTemplateArgs(); >> if (TA == nullptr) >> return nullptr; >> SoFar = make<NameWithTemplateArgs>(SoFar, TA); >> @@ -3436,7 +3391,7 @@ Node *Db::parseType() { >> break; >> } >> >> - Result = legacyParse<parse_template_param>(); >> + Result = parseTemplateParam(); >> if (Result == nullptr) >> return nullptr; >> >> @@ -3451,7 +3406,7 @@ Node *Db::parseType() { >> // parse them, take the second production. >> >> if (TryToParseTemplateArgs && look() == 'I') { >> - Node *TA = legacyParse<parse_template_args>(); >> + Node *TA = parseTemplateArgs(); >> if (TA == nullptr) >> return nullptr; >> Result = make<NameWithTemplateArgs>(Result, TA); >> @@ -3506,7 +3461,7 @@ Node *Db::parseType() { >> // ::= <substitution> # See Compression below >> case 'S': { >> if (look(1) && look(1) != 't') { >> - Node *Sub = legacyParse<parse_substitution>(); >> + Node *Sub = parseSubstitution(); >> if (Sub == nullptr) >> return nullptr; >> >> @@ -3521,7 +3476,7 @@ Node *Db::parseType() { >> // parse them, take the second production. >> >> if (TryToParseTemplateArgs && look() == 'I') { >> - Node *TA = legacyParse<parse_template_args>(); >> + Node *TA = parseTemplateArgs(); >> if (TA == nullptr) >> return nullptr; >> Result = make<NameWithTemplateArgs>(Sub, TA); >> @@ -3872,7 +3827,7 @@ Node *Db::parseExpr() { >> case 'L': >> return parseExprPrimary(); >> case 'T': >> - return legacyParse<parse_template_param>(); >> + return parseTemplateParam(); >> case 'f': >> return parseFunctionParam(); >> case 'a': >> @@ -4244,7 +4199,7 @@ Node *Db::parseExpr() { >> case 'Z': >> First += 2; >> if (look() == 'T') { >> - Node *R = legacyParse<parse_template_param>(); >> + Node *R = parseTemplateParam(); >> if (R == nullptr) >> return nullptr; >> return make<SizeofParamPackExpr>(R); >> @@ -4572,6 +4527,28 @@ template <class Float> Node *Db::parseFl >> return make<FloatExpr<Float>>(Data); >> } >> >> +// <seq-id> ::= <0-9A-Z>+ >> +bool Db::parseSeqId(size_t *Out) { >> + if (!(look() >= '0' && look() <= '9') && >> + !(look() >= 'A' && look() <= 'Z')) >> + return true; >> + >> + size_t Id = 0; >> + while (true) { >> + if (look() >= '0' && look() <= '9') { >> + Id *= 36; >> + Id += static_cast<size_t>(look() - '0'); >> + } else if (look() >= 'A' && look() <= 'Z') { >> + Id *= 36; >> + Id += static_cast<size_t>(look() - 'A') + 10; >> + } else { >> + *Out = Id; >> + return false; >> + } >> + ++First; >> + } >> +} >> + >> // <substitution> ::= S <seq-id> _ >> // ::= S_ >> // <substitution> ::= Sa # ::std::allocator >> @@ -4582,243 +4559,172 @@ template <class Float> Node *Db::parseFl >> // <substitution> ::= Si # ::std::basic_istream<char, >> std::char_traits<char> > >> // <substitution> ::= So # ::std::basic_ostream<char, >> std::char_traits<char> > >> // <substitution> ::= Sd # ::std::basic_iostream<char, >> std::char_traits<char> > >> +Node *Db::parseSubstitution() { >> + if (!consumeIf('S')) >> + return nullptr; >> >> -const char* >> -parse_substitution(const char* first, const char* last, Db& db) >> -{ >> - if (last - first >= 2) >> - { >> - if (*first == 'S') >> - { >> - switch (first[1]) >> - { >> - case 'a': >> - db.Names.push_back( >> - db.make<SpecialSubstitution>( >> - SpecialSubKind::allocator)); >> - first += 2; >> - break; >> - case 'b': >> - db.Names.push_back( >> - db.make<SpecialSubstitution>(S >> pecialSubKind::basic_string)); >> - first += 2; >> - break; >> - case 's': >> - db.Names.push_back( >> - db.make<SpecialSubstitution>( >> - SpecialSubKind::string)); >> - first += 2; >> - break; >> - case 'i': >> - db.Names.push_back(db.make<Spe >> cialSubstitution>(SpecialSubKind::istream)); >> - first += 2; >> - break; >> - case 'o': >> - db.Names.push_back(db.make<Spe >> cialSubstitution>(SpecialSubKind::ostream)); >> - first += 2; >> - break; >> - case 'd': >> - db.Names.push_back(db.make<Spe >> cialSubstitution>(SpecialSubKind::iostream)); >> - first += 2; >> - break; >> - case '_': >> - if (!db.Subs.empty()) >> - { >> - db.Names.push_back(db.Subs[0]); >> - first += 2; >> - } >> - break; >> - default: >> - if (std::isdigit(first[1]) || std::isupper(first[1])) >> - { >> - size_t sub = 0; >> - const char* t = first+1; >> - if (std::isdigit(*t)) >> - sub = static_cast<size_t>(*t - '0'); >> - else >> - sub = static_cast<size_t>(*t - 'A') + 10; >> - for (++t; t != last && (std::isdigit(*t) || >> std::isupper(*t)); ++t) >> - { >> - sub *= 36; >> - if (std::isdigit(*t)) >> - sub += static_cast<size_t>(*t - '0'); >> - else >> - sub += static_cast<size_t>(*t - 'A') + 10; >> - } >> - if (t == last || *t != '_') >> - return first; >> - ++sub; >> - if (sub < db.Subs.size()) >> - { >> - db.Names.push_back(db.Subs[sub]); >> - first = t+1; >> - } >> - } >> - break; >> - } >> - } >> + if (std::islower(look())) { >> + Node *SpecialSub; >> + switch (look()) { >> + case 'a': >> + ++First; >> + SpecialSub = make<SpecialSubstitution>(SpecialSubKind::allocator); >> + break; >> + case 'b': >> + ++First; >> + SpecialSub = make<SpecialSubstitution>(Spec >> ialSubKind::basic_string); >> + break; >> + case 's': >> + ++First; >> + SpecialSub = make<SpecialSubstitution>(SpecialSubKind::string); >> + break; >> + case 'i': >> + ++First; >> + SpecialSub = make<SpecialSubstitution>(SpecialSubKind::istream); >> + break; >> + case 'o': >> + ++First; >> + SpecialSub = make<SpecialSubstitution>(SpecialSubKind::ostream); >> + break; >> + case 'd': >> + ++First; >> + SpecialSub = make<SpecialSubstitution>(SpecialSubKind::iostream); >> + break; >> + default: >> + return nullptr; >> } >> - return first; >> + // Itanium C++ ABI 5.1.2: If a name that would use a built-in >> <substitution> >> + // has ABI tags, the tags are appended to the substitution; the >> result is a >> + // substitutable component. >> + Node *WithTags = parseAbiTags(SpecialSub); >> + if (WithTags != SpecialSub) { >> + Subs.push_back(WithTags); >> + SpecialSub = WithTags; >> + } >> + return SpecialSub; >> + } >> + >> + // ::= S_ >> + if (consumeIf('_')) { >> + if (Subs.empty()) >> + return nullptr; >> + return Subs[0]; >> + } >> + >> + // ::= S <seq-id> _ >> + size_t Index = 0; >> + if (parseSeqId(&Index)) >> + return nullptr; >> + ++Index; >> + if (!consumeIf('_') || Index >= Subs.size()) >> + return nullptr; >> + return Subs[Index]; >> } >> >> // <template-param> ::= T_ # first template parameter >> // ::= T <parameter-2 non-negative number> _ >> +Node *Db::parseTemplateParam() { >> + if (!consumeIf('T')) >> + return nullptr; >> >> -const char* >> -parse_template_param(const char* first, const char* last, Db& db) >> -{ >> - if (last - first >= 2) >> - { >> - if (*first == 'T') >> - { >> - if (first[1] == '_') >> - { >> - if (!db.TemplateParams.empty()) >> - { >> - db.Names.push_back(db.TemplateParams[0]); >> - first += 2; >> - } >> - else >> - { >> - db.Names.push_back(db.make<NameType>("T_")); >> - first += 2; >> - db.FixForwardReferences = true; >> - } >> - } >> - else if (isdigit(first[1])) >> - { >> - const char* t = first+1; >> - size_t sub = static_cast<size_t>(*t - '0'); >> - for (++t; t != last && isdigit(*t); ++t) >> - { >> - sub *= 10; >> - sub += static_cast<size_t>(*t - '0'); >> - } >> - if (t == last || *t != '_') >> - return first; >> - ++sub; >> - if (sub < db.TemplateParams.size()) >> - { >> - db.Names.push_back(db.TemplateParams[sub]); >> - first = t+1; >> - } >> - else >> - { >> - db.Names.push_back( >> - db.make<NameType>(StringView(first, t + 1))); >> - first = t+1; >> - db.FixForwardReferences = true; >> - } >> - } >> - } >> + if (consumeIf('_')) { >> + if (TemplateParams.empty()) { >> + FixForwardReferences = true; >> + return make<NameType>("FORWARD_REFERENCE"); >> } >> - return first; >> + return TemplateParams[0]; >> + } >> + >> + size_t Index; >> + if (parsePositiveInteger(&Index)) >> + return nullptr; >> + ++Index; >> + if (!consumeIf('_')) >> + return nullptr; >> + if (Index >= TemplateParams.size()) { >> + FixForwardReferences = true; >> + return make<NameType>("FORWARD_REFERENCE"); >> + } >> + return TemplateParams[Index]; >> } >> >> -// <template-arg> ::= <type> >> # type or template >> -// ::= X <expression> E >> # expression >> -// ::= <expr-primary> >> # simple expressions >> -// ::= J <template-arg>* E >> # argument pack >> -// ::= LZ <encoding> E >> # extension >> -const char* >> -parse_template_arg(const char* first, const char* last, Db& db) >> -{ >> - if (first != last) >> - { >> - const char* t; >> - switch (*first) >> - { >> - case 'X': >> - t = parse_expression(first+1, last, db); >> - if (t != first+1) >> - { >> - if (t != last && *t == 'E') >> - first = t+1; >> - } >> - break; >> - case 'J': { >> - t = first+1; >> - if (t == last) >> - return first; >> - size_t ArgsBegin = db.Names.size(); >> - while (*t != 'E') >> - { >> - const char* t1 = parse_template_arg(t, last, db); >> - if (t1 == t) >> - return first; >> - t = t1; >> - } >> - NodeArray Args = db.popTrailingNodeArray(ArgsBegin); >> - db.Names.push_back(db.make<TemplateArgumentPack>(Args)); >> - first = t+1; >> - break; >> - } >> - case 'L': >> - // <expr-primary> or LZ <encoding> E >> - if (first+1 != last && first[1] == 'Z') >> - { >> - t = parse_encoding(first+2, last, db); >> - if (t != first+2 && t != last && *t == 'E') >> - first = t+1; >> - } >> - else >> - first = parse_expr_primary(first, last, db); >> - break; >> - default: >> - // <type> >> - first = parse_type(first, last, db); >> - break; >> - } >> +// <template-arg> ::= <type> # type or template >> +// ::= X <expression> E # expression >> +// ::= <expr-primary> # simple expressions >> +// ::= J <template-arg>* E # argument pack >> +// ::= LZ <encoding> E # extension >> +Node *Db::parseTemplateArg() { >> + switch (look()) { >> + case 'X': { >> + ++First; >> + Node *Arg = parseExpr(); >> + if (Arg == nullptr || !consumeIf('E')) >> + return nullptr; >> + return Arg; >> + } >> + case 'J': { >> + ++First; >> + size_t ArgsBegin = Names.size(); >> + while (!consumeIf('E')) { >> + Node *Arg = parseTemplateArg(); >> + if (Arg == nullptr) >> + return nullptr; >> + Names.push_back(Arg); >> } >> - return first; >> + NodeArray Args = popTrailingNodeArray(ArgsBegin); >> + return make<TemplateArgumentPack>(Args); >> + } >> + case 'L': { >> + // ::= LZ <encoding> E # extension >> + if (look(1) == 'Z') { >> + First += 2; >> + Node *Arg = parseEncoding(); >> + if (Arg == nullptr || !consumeIf('E')) >> + return nullptr; >> + return Arg; >> + } >> + // ::= <expr-primary> # simple expressions >> + return parseExprPrimary(); >> + } >> + default: >> + return parseType(); >> + } >> } >> >> // <template-args> ::= I <template-arg>* E >> // extension, the abi says <template-arg>+ >> -const char* >> -parse_template_args(const char* first, const char* last, Db& db) >> -{ >> - if (last - first >= 2 && *first == 'I') >> - { >> - if (db.TagTemplates) >> - db.TemplateParams.clear(); >> - const char* t = first+1; >> - size_t begin_idx = db.Names.size(); >> - while (*t != 'E') >> - { >> - if (db.TagTemplates) >> - { >> - auto TmpParams = std::move(db.TemplateParams); >> - size_t k0 = db.Names.size(); >> - const char* t1 = parse_template_arg(t, last, db); >> - size_t k1 = db.Names.size(); >> - db.TemplateParams = std::move(TmpParams); >> - if (t1 == t || t1 == last || k0 + 1 != k1) >> - return first; >> - Node *TableEntry = db.Names.back(); >> - if (TableEntry->getKind() == Node::KTemplateArgumentPack) >> - TableEntry = db.make<ParameterPack>( >> - static_cast<TemplateArgumentPack*>(TableEntry) >> - ->getElements()); >> - db.TemplateParams.push_back(TableEntry); >> - t = t1; >> - continue; >> - } >> - size_t k0 = db.Names.size(); >> - const char* t1 = parse_template_arg(t, last, db); >> - size_t k1 = db.Names.size(); >> - if (t1 == t || t1 == last || k0 > k1) >> - return first; >> - t = t1; >> - } >> - if (begin_idx > db.Names.size()) >> - return first; >> - first = t + 1; >> - auto *tp = db.make<TemplateArgs>( >> - db.popTrailingNodeArray(begin_idx)); >> - db.Names.push_back(tp); >> +Node *Db::parseTemplateArgs() { >> + if (!consumeIf('I')) >> + return nullptr; >> + >> + // <template-params> refer to the innermost <template-args>. Clear out >> any >> + // outer args that we may have inserted into TemplateParams. >> + if (TagTemplates) >> + TemplateParams.clear(); >> + >> + size_t ArgsBegin = Names.size(); >> + while (!consumeIf('E')) { >> + if (TagTemplates) { >> + auto OldParams = std::move(TemplateParams); >> + Node *Arg = parseTemplateArg(); >> + TemplateParams = std::move(OldParams); >> + if (Arg == nullptr) >> + return nullptr; >> + Names.push_back(Arg); >> + Node *TableEntry = Arg; >> + if (Arg->getKind() == Node::KTemplateArgumentPack) { >> + TableEntry = make<ParameterPack>( >> + static_cast<TemplateArgumentPack*>(TableEntry)->getElements( >> )); >> + } >> + TemplateParams.push_back(TableEntry); >> + } else { >> + Node *Arg = parseTemplateArg(); >> + if (Arg == nullptr) >> + return nullptr; >> + Names.push_back(Arg); >> } >> - return first; >> + } >> + return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin)); >> } >> >> // <discriminator> := _ <non-negative number> # when number < 10 >> @@ -4859,183 +4765,106 @@ parse_discriminator(const char* first, c >> return first; >> } >> >> -// _block_invoke >> -// _block_invoke<decimal-digit>+ >> -// _block_invoke_<decimal-digit>+ >> - >> -const char* >> -parse_block_invoke(const char* first, const char* last, Db& db) >> -{ >> - if (last - first >= 13) >> - { >> - // FIXME: strcmp? >> - const char test[] = "_block_invoke"; >> - const char* t = first; >> - for (int i = 0; i < 13; ++i, ++t) >> - { >> - if (*t != test[i]) >> - return first; >> - } >> - if (t != last) >> - { >> - if (*t == '_') >> - { >> - // must have at least 1 decimal digit >> - if (++t == last || !std::isdigit(*t)) >> - return first; >> - ++t; >> - } >> - // parse zero or more digits >> - while (t != last && isdigit(*t)) >> - ++t; >> - } >> - if (db.Names.empty()) >> - return first; >> - db.Names.back() = >> - db.make<SpecialName>("invocation function for block in ", >> - db.Names.back()); >> - first = t; >> +// <mangled-name> ::= _Z <encoding> >> +// ::= <type> >> +// extension ::= ___Z <encoding> _block_invoke >> +// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+ >> +// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+ >> +Node *Db::parse() { >> + if (consumeIf("_Z")) { >> + Node *Encoding = parseEncoding(); >> + if (Encoding == nullptr) >> + return nullptr; >> + if (look() == '.') { >> + Encoding = make<DotSuffix>(Encoding, StringView(First, Last)); >> + First = Last; >> } >> - return first; >> -} >> + if (numLeft() != 0) >> + return nullptr; >> + return Encoding; >> + } >> >> -// extension >> -// <dot-suffix> := .<anything and everything> >> + if (consumeIf("___Z")) { >> + Node *Encoding = parseEncoding(); >> + if (Encoding == nullptr || !consumeIf("_block_invoke")) >> + return nullptr; >> + consumeIf('_'); >> + if (parseNumber().empty()) >> + return nullptr; >> + if (numLeft() != 0) >> + return nullptr; >> + return make<SpecialName>("invocation function for block in ", >> Encoding); >> + } >> >> -const char* >> -parse_dot_suffix(const char* first, const char* last, Db& db) >> -{ >> - if (first != last && *first == '.') >> - { >> - if (db.Names.empty()) >> - return first; >> - db.Names.back() = >> - db.make<DotSuffix>(db.Names.back(), StringView(first, >> last)); >> - first = last; >> - } >> - return first; >> + Node *Ty = parseType(); >> + if (numLeft() != 0) >> + return nullptr; >> + return Ty; >> } >> +} // unnamed namespace >> >> enum { >> - unknown_error = -4, >> - invalid_args = -3, >> - invalid_mangled_name, >> - memory_alloc_failure, >> - success >> + unknown_error = -4, >> + invalid_args = -3, >> + invalid_mangled_name = -2, >> + memory_alloc_failure = -1, >> + success = 0, >> }; >> >> -// <block-involcaton-function> ___Z<encoding>_block_invoke >> -// <block-involcaton-function> ___Z<encoding>_block_invoke<de >> cimal-digit>+ >> -// <block-involcaton-function> ___Z<encoding>_block_invoke_<d >> ecimal-digit>+ >> -// <mangled-name> ::= _Z<encoding> >> -// ::= <type> >> -void >> -demangle(const char* first, const char* last, Db& db, int& status) >> -{ >> - if (first >= last) >> - { >> - status = invalid_mangled_name; >> - return; >> - } >> - if (*first == '_') >> - { >> - if (last - first >= 4) >> - { >> - if (first[1] == 'Z') >> - { >> - const char* t = parse_encoding(first+2, last, db); >> - if (t != first+2 && t != last && *t == '.') >> - t = parse_dot_suffix(t, last, db); >> - if (t != last) >> - status = invalid_mangled_name; >> - } >> - else if (first[1] == '_' && first[2] == '_' && first[3] == >> 'Z') >> - { >> - const char* t = parse_encoding(first+4, last, db); >> - if (t != first+4 && t != last) >> - { >> - const char* t1 = parse_block_invoke(t, last, db); >> - if (t1 != last) >> - status = invalid_mangled_name; >> - } >> - else >> - status = invalid_mangled_name; >> - } >> - else >> - status = invalid_mangled_name; >> - } >> - else >> - status = invalid_mangled_name; >> - } >> - else >> - { >> - const char* t = parse_type(first, last, db); >> - if (t != last) >> - status = invalid_mangled_name; >> - } >> - if (status == success && db.Names.empty()) >> - status = invalid_mangled_name; >> -} >> - >> -} // unnamed namespace >> - >> - >> namespace __cxxabiv1 { >> extern "C" _LIBCXXABI_FUNC_VIS char * >> -__cxa_demangle(const char *mangled_name, char *buf, size_t *n, int >> *status) { >> - if (mangled_name == nullptr || (buf != nullptr && n == nullptr)) >> - { >> - if (status) >> - *status = invalid_args; >> - return nullptr; >> - } >> - >> - size_t internal_size = buf != nullptr ? *n : 0; >> - Db db; >> - int internal_status = success; >> - size_t len = std::strlen(mangled_name); >> - demangle(mangled_name, mangled_name + len, db, >> - internal_status); >> - >> - if (internal_status == success && db.FixForwardReferences && >> - !db.TemplateParams.empty()) >> - { >> - db.FixForwardReferences = false; >> - db.TagTemplates = false; >> - db.Names.clear(); >> - db.Subs.clear(); >> - demangle(mangled_name, mangled_name + len, db, internal_status); >> - if (db.FixForwardReferences) >> - internal_status = invalid_mangled_name; >> - } >> - >> - if (internal_status == success && >> - db.Names.back()->containsUnexpandedParameterPack()) >> - internal_status = invalid_mangled_name; >> - >> - if (internal_status == success) >> - { >> - if (!buf) >> - { >> - internal_size = 1024; >> - buf = static_cast<char*>(std::malloc(internal_size)); >> - } >> +__cxa_demangle(const char *MangledName, char *Buf, size_t *N, int >> *Status) { >> + if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) { >> + if (Status) >> + *Status = invalid_args; >> + return nullptr; >> + } >> >> - if (buf) >> - { >> - OutputStream s(buf, internal_size); >> - db.Names.back()->print(s); >> - s += '\0'; >> - if (n) *n = s.getCurrentPosition(); >> - buf = s.getBuffer(); >> - } >> - else >> - internal_status = memory_alloc_failure; >> - } >> - else >> - buf = nullptr; >> - if (status) >> - *status = internal_status; >> - return buf; >> + size_t BufSize = Buf != nullptr ? *N : 0; >> + int InternalStatus = success; >> + size_t MangledNameLength = std::strlen(MangledName); >> + >> + Db Parser(MangledName, MangledName + MangledNameLength); >> + Node *AST = Parser.parse(); >> + >> + if (AST == nullptr) >> + InternalStatus = invalid_mangled_name; >> + >> + if (InternalStatus == success && Parser.FixForwardReferences && >> + !Parser.TemplateParams.empty()) { >> + Parser.FixForwardReferences = false; >> + Parser.TagTemplates = false; >> + Parser.Names.clear(); >> + Parser.Subs.clear(); >> + Parser.First = MangledName; >> + Parser.Last = MangledName + MangledNameLength; >> + AST = Parser.parse(); >> + if (AST == nullptr || Parser.FixForwardReferences) >> + InternalStatus = invalid_mangled_name; >> + } >> + >> + if (InternalStatus == success && AST->containsUnexpandedParamet >> erPack()) >> + InternalStatus = invalid_mangled_name; >> + >> + if (InternalStatus == success) { >> + if (Buf == nullptr) { >> + BufSize = 1024; >> + Buf = static_cast<char*>(std::malloc(BufSize)); >> + } >> + >> + if (Buf) { >> + OutputStream Stream(Buf, BufSize); >> + AST->print(Stream); >> + Stream += '\0'; >> + if (N != nullptr) >> + *N = Stream.getCurrentPosition(); >> + Buf = Stream.getBuffer(); >> + } else >> + InternalStatus = memory_alloc_failure; >> + } >> + >> + if (Status) >> + *Status = InternalStatus; >> + return InternalStatus == success ? Buf : nullptr; >> } >> } // __cxxabiv1 >> >> Modified: libcxxabi/trunk/test/test_demangle.pass.cpp >> URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/tes >> t_demangle.pass.cpp?rev=326797&r1=326796&r2=326797&view=diff >> ============================================================ >> ================== >> --- libcxxabi/trunk/test/test_demangle.pass.cpp (original) >> +++ libcxxabi/trunk/test/test_demangle.pass.cpp Tue Mar 6 06:21:10 2018 >> @@ -29713,6 +29713,9 @@ const char* cases[][2] = >> >> {"_ZNKR4llvm8OptionalINS_11MCFixupKindEEdeEv", >> "llvm::Optional<llvm::MCFixupKind>::operator*() const &"}, >> {"_ZZL23isValidCoroutineContextRN5clang4SemaENS_14SourceLoc >> ationEN4llvm9StringRefEENK3$_4clEZL23isValidCoroutineContextS1_S2_S4_E15InvalidFuncDiag", >> "isValidCoroutineContext(clang::Sema&, clang::SourceLocation, >> llvm::StringRef)::$_4::operator()(isValidCoroutineContext(clang::Sema&, >> clang::SourceLocation, llvm::StringRef)::InvalidFuncDiag) const"}, >> + >> + // ABI tags can apply to built-in substitutions. >> + {"_Z1fSsB1XS_", "f(std::string[abi:X], std::string[abi:X])"}, >> }; >> >> const unsigned N = sizeof(cases) / sizeof(cases[0]); >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits@lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >> > > >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits