[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