erik.pilkington updated this revision to Diff 99930.
erik.pilkington added a comment.

In this new patch:

- Add the testcase from https://reviews.llvm.org/D33393
- Add an assert() that k0 <= k1
- Use std::for_each instead of the for loop

Thanks for taking a look,
Erik


https://reviews.llvm.org/D33368

Files:
  src/cxa_demangle.cpp
  test/test_demangle.pass.cpp

Index: test/test_demangle.pass.cpp
===================================================================
--- test/test_demangle.pass.cpp
+++ test/test_demangle.pass.cpp
@@ -29604,6 +29604,7 @@
     {"PFvRmOE", "void (*)(unsigned long&) &&"},
     {"_ZTW1x", "thread-local wrapper routine for x"},
     {"_ZTHN3fooE", "thread-local initialization routine for foo"},
+    {"_Z4algoIJiiiEEvZ1gEUlT_E_", "void algo<int, int, int>(g::'lambda'(int, int, int))"},
 };
 
 const unsigned N = sizeof(cases) / sizeof(cases[0]);
@@ -29664,7 +29665,8 @@
     "\x44\x74\x71\x75\x35\x2A\xDF\x74\x44\x61\x73\x63\x35\x2A\x3B\x41\x72\x4D\x6E\x65\x34\x9F\xC1\x63\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x6C\x53\xF9\x5F\x70\x74\x70\x69\x45\x33\x44\x76\x35",
     "\x44\x74\x70\x74\x71\x75\x32\x43\x41\x38\x65\x6E\x9B\x72\x4D\xC1\x43\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x6C\x53\xF9\x5F\x70\x74\x70\x69\x45\x38\xD3\x73\x9E\x2A\x37",
     "\x46\x44\x74\x70\x74\x71\x75\x32\x43\x41\x72\x4D\x6E\x65\x34\x9F\xC1\x43\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x6C\x53\xF9\x5F\x70\x74\x70\x69\x45\x34\xD3\x73\x9E\x2A\x37\x72\x33\x8E\x3A\x29\x8E\x44\x35",
-	"_ZcvCiIJEEDvT__FFFFT_vT_v",
+    "_ZcvCiIJEEDvT__FFFFT_vT_v",
+    "Z1JIJ1_T_EE3o00EUlT_E0",
 };
 
 const unsigned NI = sizeof(invalid_cases) / sizeof(invalid_cases[0]);
Index: src/cxa_demangle.cpp
===================================================================
--- src/cxa_demangle.cpp
+++ src/cxa_demangle.cpp
@@ -3015,6 +3015,7 @@
             break;
         case 'l':
           {
+            size_t lambda_pos = db.names.size();
             db.names.push_back(typename C::String("'lambda'("));
             const char* t0 = first+2;
             if (first[2] == 'v')
@@ -3024,36 +3025,41 @@
             }
             else
             {
-                const char* t1 = parse_type(t0, last, db);
-                if (t1 == t0)
-                {
-                    if(!db.names.empty())
-                        db.names.pop_back();
-                    return first;
-                }
-                if (db.names.size() < 2)
-                    return first;
-                auto tmp = db.names.back().move_full();
-                db.names.pop_back();
-                db.names.back().first.append(tmp);
-                t0 = t1;
+                bool is_first_it = true;
                 while (true)
                 {
-                    t1 = parse_type(t0, last, db);
+                    long k0 = static_cast<long>(db.names.size());
+                    const char* t1 = parse_type(t0, last, db);
+                    long k1 = static_cast<long>(db.names.size());
                     if (t1 == t0)
                         break;
-                    if (db.names.size() < 2)
+                    assert(k0 <= k1 && "parse_type() mutated the name stack");
+                    if (k1 == k0)
                         return first;
-                    tmp = db.names.back().move_full();
-                    db.names.pop_back();
-                    if (!tmp.empty())
-                    {
-                        db.names.back().first.append(", ");
-                        db.names.back().first.append(tmp);
-                    }
+                    // If the call to parse_type above found a pack expansion
+                    // substitution, then multiple names could have been
+                    // inserted into the name table. Walk through the names,
+                    // appending each onto the lambda's parameter list.
+                    std::for_each(db.names.begin() + k0, db.names.begin() + k1,
+                                  [&](typename C::sub_type::value_type &pair) {
+                                      if (pair.empty())
+                                          return;
+                                      auto &lambda = db.names[lambda_pos].first;
+                                      if (!is_first_it)
+                                          lambda.append(", ");
+                                      is_first_it = false;
+                                      lambda.append(pair.move_full());
+                                  });
+                    db.names.erase(db.names.begin() + k0, db.names.end());
                     t0 = t1;
                 }
-                if(db.names.empty())
+                if (is_first_it)
+                {
+                    if (!db.names.empty())
+                        db.names.pop_back();
+                    return first;
+                }
+                if (db.names.empty() || db.names.size() - 1 != lambda_pos)
                   return first;
                 db.names.back().first.append(")");
             }
@@ -4964,6 +4970,7 @@
         string_pair(const char (&s)[N]) : first(s, N-1) {}
 
     size_t size() const {return first.size() + second.size();}
+    bool empty() const { return first.empty() && second.empty(); }
     StrT full() const {return first + second;}
     StrT move_full() {return std::move(first) + std::move(second);}
 };
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to