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>( > SpecialSubKind::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<SpecialSubstitution>( > SpecialSubKind::istream)); > - first += 2; > - break; > - case 'o': > - db.Names.push_back(db.make<SpecialSubstitution>( > SpecialSubKind::ostream)); > - first += 2; > - break; > - case 'd': > - db.Names.push_back(db.make<SpecialSubstitution>( > 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>( > SpecialSubKind::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< > decimal-digit>+ > -// <block-involcaton-function> ___Z<encoding>_block_invoke_< > decimal-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->containsUnexpandedParameterPac > k()) > + 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/ > test_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_ > 14SourceLocationEN4llvm9StringRefEENK3$_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