[libcxxabi] r326797 - [demangler] Modernize the rest of the demangler.
Erik Pilkington via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 6 06:21:10 PST 2018
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->containsUnexpandedParameterPack())
+ 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]);
More information about the cfe-commits
mailing list