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