erik.pilkington updated this revision to Diff 110281.
erik.pilkington marked 14 inline comments as done.
erik.pilkington added a comment.

Address review comments.
Thanks!
Erik


https://reviews.llvm.org/D36427

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

Index: test/unittest_demangle.pass.cpp
===================================================================
--- /dev/null
+++ test/unittest_demangle.pass.cpp
@@ -0,0 +1,123 @@
+//===----------------------- unittest_demangle.cpp ------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../src/cxa_demangle.cpp"
+
+using namespace __cxxabiv1;
+
+void testPODSmallVector() {
+  { // {push/pop}_back
+    PODSmallVector<int, 1> PSV;
+    PSV.push_back(0);
+    PSV.push_back(1);
+    PSV.push_back(2);
+    PSV.push_back(3);
+    for (int i = 0; i < 4; ++i)
+      assert(PSV[i] == i);
+    PSV.pop_back();
+    for (int i = 0; i < 3; ++i)
+      assert(PSV[i] == i);
+    PSV.pop_back();
+    PSV.pop_back();
+    assert(!PSV.empty() && PSV.size() == 1);
+    PSV.pop_back();
+    assert(PSV.empty() && PSV.size() == 0);
+  }
+
+  {
+    PODSmallVector<int, 1> PSV1;
+    PSV1.push_back(1);
+    PSV1.push_back(2);
+    PSV1.push_back(3);
+
+    PODSmallVector<int, 1> PSV2;
+    std::swap(PSV1, PSV2);
+    assert(PSV1.size() == 0);
+    assert(PSV2.size() == 3);
+    int i = 1;
+    for (int x : PSV2) {
+      assert(x == i);
+      ++i;
+    }
+    assert(i == 4);
+    std::swap(PSV1, PSV2);
+    assert(PSV1.size() == 3);
+    assert(PSV2.size() == 0);
+    i = 1;
+    for (int x : PSV1) {
+      assert(x == i);
+      ++i;
+    }
+    assert(i == 4);
+  }
+
+  {
+    PODSmallVector<int, 10> PSV1;
+    PODSmallVector<int, 10> PSV2;
+    PSV1.push_back(0);
+    PSV1.push_back(1);
+    PSV1.push_back(2);
+    assert(PSV1.size() == 3);
+    assert(PSV2.size() == 0);
+    std::swap(PSV1, PSV2);
+    assert(PSV1.size() == 0);
+    assert(PSV2.size() == 3);
+    int i = 0;
+    for (int x : PSV2) {
+      assert(x == i);
+      ++i;
+    }
+    for (int x : PSV1) {
+      assert(false);
+      (void)x;
+    }
+  }
+}
+
+void testSubstitutionTable() {
+  {
+    SubstitutionTable<2> Tab;
+
+    NameType Names[] = { {"MERP"}, {"MARP"}, {"MAMP"} };
+    Tab.pushPack();
+    Tab.pushSubstitutionIntoPack(&Names[0]);
+    Tab.pushSubstitutionIntoPack(&Names[1]);
+    Tab.pushSubstitutionIntoPack(&Names[2]);
+
+    int Index = 0;
+    for (Node *N : Tab.nthSubstitution(0)) {
+      assert(static_cast<NameType *>(N)->getName() == Names[Index].getName());
+      ++Index;
+    }
+    assert(Index == 3);
+
+    Tab.popPack();
+    assert(Tab.empty() && Tab.size() == 0);
+    Tab.pushSubstitution(&Names[0]);
+    Tab.pushSubstitution(&Names[1]);
+    assert(!Tab.empty() && Tab.size() == 2);
+
+    int I = 0;
+    for (Node *N : Tab.nthSubstitution(0)) {
+      assert(static_cast<NameType*>(N)->getName() == "MERP");
+      assert(I == 0);
+      ++I;
+    }
+    for (Node *N : Tab.nthSubstitution(1)) {
+      assert(static_cast<NameType*>(N)->getName() == "MARP");
+      assert(I == 1);
+      ++I;
+    }
+  }
+}
+
+int main() {
+  testPODSmallVector();
+  testSubstitutionTable();
+}
Index: src/cxa_demangle.cpp
===================================================================
--- src/cxa_demangle.cpp
+++ src/cxa_demangle.cpp
@@ -1407,117 +1407,6 @@
   }
 };
 
-template <std::size_t N>
-class arena
-{
-    static const std::size_t alignment = 16;
-    alignas(alignment) char buf_[N];
-    char* ptr_;
-
-    std::size_t 
-    align_up(std::size_t n) noexcept
-        {return (n + (alignment-1)) & ~(alignment-1);}
-
-    bool
-    pointer_in_buffer(char* p) noexcept
-        {return buf_ <= p && p <= buf_ + N;}
-
-public:
-    arena() noexcept : ptr_(buf_) {}
-    ~arena() {ptr_ = nullptr;}
-    arena(const arena&) = delete;
-    arena& operator=(const arena&) = delete;
-
-    char* allocate(std::size_t n);
-    void deallocate(char* p, std::size_t n) noexcept;
-
-    static constexpr std::size_t size() {return N;}
-    std::size_t used() const {return static_cast<std::size_t>(ptr_ - buf_);}
-    void reset() {ptr_ = buf_;}
-};
-
-template <std::size_t N>
-char*
-arena<N>::allocate(std::size_t n)
-{
-    n = align_up(n);
-    if (static_cast<std::size_t>(buf_ + N - ptr_) >= n)
-    {
-        char* r = ptr_;
-        ptr_ += n;
-        return r;
-    }
-    return static_cast<char*>(std::malloc(n));
-}
-
-template <std::size_t N>
-void
-arena<N>::deallocate(char* p, std::size_t n) noexcept
-{
-    if (pointer_in_buffer(p))
-    {
-        n = align_up(n);
-        if (p + n == ptr_)
-            ptr_ = p;
-    }
-    else
-        std::free(p);
-}
-
-template <class T, std::size_t N>
-class short_alloc
-{
-    arena<N>& a_;
-public:
-    typedef T value_type;
-
-public:
-    template <class _Up> struct rebind {typedef short_alloc<_Up, N> other;};
-
-    short_alloc(arena<N>& a) noexcept : a_(a) {}
-    template <class U>
-        short_alloc(const short_alloc<U, N>& a) noexcept
-            : a_(a.a_) {}
-    short_alloc(const short_alloc&) = default;
-    short_alloc& operator=(const short_alloc&) = delete;
-
-    T* allocate(std::size_t n)
-    {
-        return reinterpret_cast<T*>(a_.allocate(n*sizeof(T)));
-    }
-    void deallocate(T* p, std::size_t n) noexcept
-    {
-        a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
-    }
-
-    template <class T1, std::size_t N1, class U, std::size_t M>
-    friend
-    bool
-    operator==(const short_alloc<T1, N1>& x, const short_alloc<U, M>& y) noexcept;
-
-    template <class U, std::size_t M> friend class short_alloc;
-};
-
-template <class T, std::size_t N, class U, std::size_t M>
-inline
-bool
-operator==(const short_alloc<T, N>& x, const short_alloc<U, M>& y) noexcept
-{
-    return N == M && &x.a_ == &y.a_;
-}
-
-template <class T, std::size_t N, class U, std::size_t M>
-inline
-bool
-operator!=(const short_alloc<T, N>& x, const short_alloc<U, M>& y) noexcept
-{
-    return !(x == y);
-}
-
-const size_t bs = 4 * 1024;
-template <class T> using Alloc = short_alloc<T, bs>;
-template <class T> using Vector = std::vector<T, Alloc<T>>;
-
 class BumpPointerAllocator {
   struct BlockMeta {
     BlockMeta* Next;
@@ -1568,13 +1457,202 @@
   }
 };
 
+template <class T, size_t N> class PODSmallVector {
+  static_assert(std::is_pod<T>::value,
+                "T is required to be a plain old data type");
+
+  T *First;
+  T *Last;
+  T *Cap;
+  T Inline[N];
+
+  bool isInline() const { return First == Inline; }
+
+  void clearInline() {
+    First = Inline;
+    Last = Inline;
+    Cap = Inline + N;
+  }
+
+  void reserve(size_t NewCap) {
+    size_t S = size();
+    if (isInline()) {
+      auto *Tmp = static_cast<T *>(std::malloc(NewCap * sizeof(T)));
+      std::copy(First, Last, Tmp);
+      First = Tmp;
+    } else
+      First = static_cast<T *>(std::realloc(First, NewCap * sizeof(T)));
+    Last = First + S;
+    Cap = First + NewCap;
+  }
+
+public:
+  PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
+
+  PODSmallVector(const PODSmallVector &) = delete;
+  PODSmallVector &operator=(const PODSmallVector &) = delete;
+
+  PODSmallVector(PODSmallVector &&Other) : PODSmallVector() {
+    if (Other.isInline()) {
+      std::copy(Other.begin(), Other.end(), First);
+      Last = First + Other.size();
+      Other.clear();
+      return;
+    }
+
+    First = Other.First;
+    Last = Other.Last;
+    Cap = Other.Cap;
+    Other.clearInline();
+  }
+
+  PODSmallVector &operator=(PODSmallVector &&Other) {
+    if (Other.isInline()) {
+      if (!isInline()) {
+        std::free(First);
+        clearInline();
+      }
+      std::copy(Other.begin(), Other.end(), First);
+      Last = First + Other.size();
+      Other.clear();
+      return *this;
+    }
+
+    if (isInline()) {
+      First = Other.First;
+      Last = Other.Last;
+      Cap = Other.Cap;
+      Other.clearInline();
+      return *this;
+    }
+
+    std::swap(First, Other.First);
+    std::swap(Last, Other.Last);
+    std::swap(Cap, Other.Cap);
+    Other.clear();
+    return *this;
+  }
+
+  void push_back(const T &Elem) {
+    if (Last == Cap)
+      reserve(size() * 2);
+    *Last++ = Elem;
+  }
+
+  void pop_back() {
+    assert(Last != First && "Popping empty vector!");
+    --Last;
+  }
+
+  void dropBack(size_t Index) {
+    assert(Index <= size() && "dropBack() can't expand!");
+    Last = First + Index;
+  }
+
+  T *begin() { return First; }
+  T *end() { return Last; }
+
+  bool empty() const { return First == Last; }
+  size_t size() const { return static_cast<size_t>(Last - First); }
+  T &back() {
+    assert(Last != First && "Calling back() on empty vector!");
+    return *(Last - 1);
+  }
+  T &operator[](size_t Index) {
+    assert(Index < size() && "Invalid access!");
+    return *(begin() + Index);
+  }
+  void clear() { Last = First; }
+
+  ~PODSmallVector() {
+    if (!isInline())
+      std::free(First);
+  }
+};
+
+// Substitution table. This type is used to track the substitutions that are
+// known by the parser.
+template <size_t Size> class SubstitutionTable {
+  // Substitutions hold the actual entries in the table, and PackIndices tells
+  // us which entries are members of which pack. For example, if the
+  // substitutions we're tracking are: {int, {float, FooBar}, char}, with
+  // {float, FooBar} being a parameter pack, we represent the substitutions as:
+  // Substitutions: int, float, FooBar, char
+  // PackIndices:     0,             1,    3
+  // So, PackIndicies[I] holds the offset of the begin of the Ith pack, and
+  // PackIndices[I + 1] holds the offset of the end.
+  PODSmallVector<Node *, Size> Substitutions;
+  PODSmallVector<unsigned, Size> PackIndices;
+
+public:
+  // Add a substitution that represents a single name to the table. This is
+  // modeled as a parameter pack with just one element.
+  void pushSubstitution(Node *Entry) {
+    pushPack();
+    pushSubstitutionIntoPack(Entry);
+  }
+
+  // Add a new empty pack to the table. Subsequent calls to
+  // pushSubstitutionIntoPack() will add to this pack.
+  void pushPack() {
+    PackIndices.push_back(static_cast<unsigned>(Substitutions.size()));
+  }
+  void pushSubstitutionIntoPack(Node *Entry) {
+    assert(!PackIndices.empty() && "No pack to push substitution into!");
+    Substitutions.push_back(Entry);
+  }
+
+  // Remove the last pack from the table.
+  void popPack() {
+    unsigned Last = PackIndices.back();
+    PackIndices.pop_back();
+    Substitutions.dropBack(Last);
+  }
+
+  // For use in a range-for loop.
+  struct NodeRange {
+    Node **First;
+    Node **Last;
+    Node **begin() { return First; }
+    Node **end() { return Last; }
+  };
+
+  // Retrieve the Nth substitution. This is represented as a range, as the
+  // substitution could be referring to a parameter pack.
+  NodeRange nthSubstitution(size_t N) {
+    assert(N < PackIndices.size());
+    // The Nth parameter pack starts at offset PackIndices[N], and ends at
+    // PackIndices[N + 1].
+    Node **Begin = Substitutions.begin() + PackIndices[N];
+    Node **End = (N + 1 == PackIndices.size())
+                     ? Substitutions.end()
+                     : Substitutions.begin() + PackIndices[N + 1];
+    assert(End <= Substitutions.end() && Begin <= End);
+    return NodeRange{Begin, End};
+  }
+
+  size_t size() const { return PackIndices.size(); }
+  bool empty() const { return PackIndices.empty(); }
+  void clear() {
+    Substitutions.clear();
+    PackIndices.clear();
+  }
+};
+
 struct Db
 {
-    typedef Vector<Node*> sub_type;
-    typedef Vector<sub_type> template_param_type;
-    sub_type Names;
-    template_param_type Subs;
-    Vector<template_param_type> TemplateParams;
+    // Name stack, this is used by the parser to hold temporary names that were
+    // parsed. The parser colapses multiple names into new nodes to construct
+    // the AST. Once the parser is finished, names.size() == 1.
+    PODSmallVector<Node *, 32> Names;
+
+    // Substitution table. Itanium supports name substitutions as a means of
+    // compression. The string "S42_" refers to the 42nd entry in this table.
+    SubstitutionTable<32> Subs;
+
+    // Template parameter table. Like the above, but referenced like "T42_".
+    SubstitutionTable<4> TemplateParams;
+
     Qualifiers CV = QualNone;
     FunctionRefQual RefQuals = FrefQualNone;
     unsigned EncodingDepth = 0;
@@ -1585,13 +1663,6 @@
 
     BumpPointerAllocator ASTAllocator;
 
-    template <size_t N>
-    Db(arena<N>& ar) :
-        Names(ar),
-        Subs(0, Names, ar),
-        TemplateParams(0, Subs, ar)
-    {}
-
     template <class T, class... Args> T* make(Args&& ...args)
     {
         return new (ASTAllocator.allocate(sizeof(T)))
@@ -1612,7 +1683,7 @@
         assert(FromPosition <= Names.size());
         NodeArray res = makeNodeArray(
             Names.begin() + (long)FromPosition, Names.end());
-        Names.erase(Names.begin() + (long)FromPosition, Names.end());
+        Names.dropBack(FromPosition);
         return res;
     }
 };
@@ -1801,7 +1872,7 @@
             case '_':
                 if (!db.Subs.empty())
                 {
-                    for (const auto& n : db.Subs.front())
+                    for (Node* n : db.Subs.nthSubstitution(0))
                         db.Names.push_back(n);
                     first += 2;
                 }
@@ -1828,7 +1899,7 @@
                     ++sub;
                     if (sub < db.Subs.size())
                     {
-                        for (const auto& n : db.Subs[sub])
+                        for (Node* n : db.Subs.nthSubstitution(sub))
                             db.Names.push_back(n);
                         first = t+1;
                     }
@@ -2058,11 +2129,9 @@
         {
             if (first[1] == '_')
             {
-                if (db.TemplateParams.empty())
-                    return first;
-                if (!db.TemplateParams.back().empty())
+                if (!db.TemplateParams.empty())
                 {
-                    for (auto& t : db.TemplateParams.back().front())
+                    for (Node *t : db.TemplateParams.nthSubstitution(0))
                         db.Names.push_back(t);
                     first += 2;
                 }
@@ -2082,12 +2151,12 @@
                     sub *= 10;
                     sub += static_cast<size_t>(*t - '0');
                 }
-                if (t == last || *t != '_' || db.TemplateParams.empty())
+                if (t == last || *t != '_')
                     return first;
                 ++sub;
-                if (sub < db.TemplateParams.back().size())
+                if (sub < db.TemplateParams.size())
                 {
-                    for (auto& temp : db.TemplateParams.back()[sub])
+                    for (Node *temp : db.TemplateParams.nthSubstitution(sub))
                         db.Names.push_back(temp);
                     first = t+1;
                 }
@@ -2469,7 +2538,7 @@
             size_t k1 = db.Names.size();
             if (t != first && k1 == k0 + 1)
             {
-                db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                db.Subs.pushSubstitution(db.Names.back());
                 first = t;
             }
             else
@@ -2485,7 +2554,7 @@
             {
                 if (db.Names.empty())
                     return first;
-                db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                db.Subs.pushSubstitution(db.Names.back());
                 first = t;
             }
             break;
@@ -2504,7 +2573,7 @@
                             return first;
                         db.Names.back() =
                             db.make<StdQualifiedName>(db.Names.back());
-                        db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                        db.Subs.pushSubstitution(db.Names.back());
                         first = t;
                     }
                 }
@@ -2959,8 +3028,7 @@
                 db.Names.begin() + (long)expr_list_begin);
             auto* conv_expr = db.make<ConversionExpr>(
                 types, expressions);
-            db.Names.erase(
-                db.Names.begin() + (long)type_begin, db.Names.end());
+            db.Names.dropBack(type_begin);
             db.Names.push_back(conv_expr);
             first = t;
         }
@@ -3313,8 +3381,8 @@
                     if (t1 != t)
                     {
                         if (is_function)
-                            db.Subs.pop_back();
-                        db.Subs.emplace_back(db.Names.get_allocator());
+                            db.Subs.popPack();
+                        db.Subs.pushPack();
                         for (size_t k = k0; k < k1; ++k)
                         {
                             if (cv) {
@@ -3325,7 +3393,7 @@
                                     db.Names[k] =
                                         db.make<QualType>(db.Names[k], cv);
                             }
-                            db.Subs.back().push_back(db.Names[k]);
+                            db.Subs.pushSubstitutionIntoPack(db.Names[k]);
                         }
                         first = t1;
                     }
@@ -3350,7 +3418,7 @@
                             if (db.Names.empty())
                                 return first;
                             first = t;
-                            db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                            db.Subs.pushSubstitution(db.Names.back());
                         }
                         break;
                     case 'C':
@@ -3362,7 +3430,7 @@
                             db.Names.back() = db.make<PostfixQualifiedType>(
                                 db.Names.back(), " complex");
                             first = t;
-                            db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                            db.Subs.pushSubstitution(db.Names.back());
                         }
                         break;
                     case 'F':
@@ -3372,7 +3440,7 @@
                             if (db.Names.empty())
                                 return first;
                             first = t;
-                            db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                            db.Subs.pushSubstitution(db.Names.back());
                         }
                         break;
                     case 'G':
@@ -3384,7 +3452,7 @@
                             db.Names.back() = db.make<PostfixQualifiedType>(
                                 db.Names.back(), " imaginary");
                             first = t;
-                            db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                            db.Subs.pushSubstitution(db.Names.back());
                         }
                         break;
                     case 'M':
@@ -3394,7 +3462,7 @@
                             if (db.Names.empty())
                                 return first;
                             first = t;
-                            db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                            db.Subs.pushSubstitution(db.Names.back());
                         }
                         break;
                     case 'O':
@@ -3404,12 +3472,12 @@
                         size_t k1 = db.Names.size();
                         if (t != first+1)
                         {
-                            db.Subs.emplace_back(db.Names.get_allocator());
+                            db.Subs.pushPack();
                             for (size_t k = k0; k < k1; ++k)
                             {
                                 db.Names[k] =
                                     db.make<RValueReferenceType>(db.Names[k]);
-                                db.Subs.back().push_back(db.Names[k]);
+                                db.Subs.pushSubstitutionIntoPack(db.Names[k]);
                             }
                             first = t;
                         }
@@ -3422,11 +3490,11 @@
                         size_t k1 = db.Names.size();
                         if (t != first+1)
                         {
-                            db.Subs.emplace_back(db.Names.get_allocator());
+                            db.Subs.pushPack();
                             for (size_t k = k0; k < k1; ++k)
                             {
                                 db.Names[k] = db.make<PointerType>(db.Names[k]);
-                                db.Subs.back().push_back(db.Names[k]);
+                                db.Subs.pushSubstitutionIntoPack(db.Names[k]);
                             }
                             first = t;
                         }
@@ -3439,12 +3507,12 @@
                         size_t k1 = db.Names.size();
                         if (t != first+1)
                         {
-                            db.Subs.emplace_back(db.Names.get_allocator());
+                            db.Subs.pushPack();
                             for (size_t k = k0; k < k1; ++k)
                             {
                                 db.Names[k] =
                                     db.make<LValueReferenceType>(db.Names[k]);
-                                db.Subs.back().push_back(db.Names[k]);
+                                db.Subs.pushSubstitutionIntoPack(db.Names[k]);
                             }
                             first = t;
                         }
@@ -3457,9 +3525,9 @@
                         size_t k1 = db.Names.size();
                         if (t != first)
                         {
-                            db.Subs.emplace_back(db.Names.get_allocator());
+                            db.Subs.pushPack();
                             for (size_t k = k0; k < k1; ++k)
-                                db.Subs.back().push_back(db.Names[k]);
+                                db.Subs.pushSubstitutionIntoPack(db.Names[k]);
                             if (db.TryToParseTemplateArgs && k1 == k0+1)
                             {
                                 const char* t1 = parse_template_args(t, last, db);
@@ -3470,9 +3538,7 @@
                                     db.Names.back() = db.make<
                                         NameWithTemplateArgs>(
                                         db.Names.back(), args);
-                                    db.Subs.push_back(Db::sub_type(
-                                        1, db.Names.back(),
-                                        db.Names.get_allocator()));
+                                    db.Subs.pushSubstitution(db.Names.back());
                                     t = t1;
                                 }
                             }
@@ -3512,7 +3578,7 @@
                                             db.Names.push_back(db.make<VendorExtQualType>(type, proto));
                                         }
                                     }
-                                    db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                                    db.Subs.pushSubstitution(db.Names.back());
                                     first = t2;
                                 }
                             }
@@ -3526,7 +3592,7 @@
                             {
                                 if (db.Names.empty())
                                     return first;
-                                db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                                db.Subs.pushSubstitution(db.Names.back());
                                 first = t;
                             }
                         }
@@ -3551,7 +3617,7 @@
                                           NameWithTemplateArgs>(
                                               db.Names.back(), template_args);
                                         // Need to create substitution for <template-template-param> <template-args>
-                                        db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                                        db.Subs.pushSubstitution(db.Names.back());
                                         first = t;
                                     }
                                 }
@@ -3570,9 +3636,9 @@
                                 size_t k1 = db.Names.size();
                                 if (t != first+2)
                                 {
-                                    db.Subs.emplace_back(db.Names.get_allocator());
+                                    db.Subs.pushPack();
                                     for (size_t k = k0; k < k1; ++k)
-                                        db.Subs.back().push_back(db.Names[k]);
+                                        db.Subs.pushSubstitutionIntoPack(db.Names[k]);
                                     first = t;
                                     return first;
                                 }
@@ -3585,7 +3651,7 @@
                                 {
                                     if (db.Names.empty())
                                         return first;
-                                    db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                                    db.Subs.pushSubstitution(db.Names.back());
                                     first = t;
                                     return first;
                                 }
@@ -3596,7 +3662,7 @@
                                 {
                                     if (db.Names.empty())
                                         return first;
-                                    db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                                    db.Subs.pushSubstitution(db.Names.back());
                                     first = t;
                                     return first;
                                 }
@@ -3619,7 +3685,7 @@
                             {
                                 if (db.Names.empty())
                                     return first;
-                                db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                                db.Subs.pushSubstitution(db.Names.back());
                                 first = t;
                             }
                         }
@@ -5119,27 +5185,35 @@
     if (last - first >= 2 && *first == 'I')
     {
         if (db.TagTemplates)
-            db.TemplateParams.back().clear();
+            db.TemplateParams.clear();
         const char* t = first+1;
         size_t begin_idx = db.Names.size();
         while (*t != 'E')
         {
             if (db.TagTemplates)
-                db.TemplateParams.emplace_back(db.Names.get_allocator());
-            size_t k0 = db.Names.size();
-            const char* t1 = parse_template_arg(t, last, db);
-            size_t k1 = db.Names.size();
-            if (db.TagTemplates)
-                db.TemplateParams.pop_back();
-            if (t1 == t || t1 == last || k0 > k1)
-                return first;
-            if (db.TagTemplates)
             {
-                db.TemplateParams.back().emplace_back(db.Names.get_allocator());
+                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 > k1)
+                    return first;
+                db.TemplateParams.pushPack();
                 for (size_t k = k0; k < k1; ++k)
-                    db.TemplateParams.back().back().push_back(db.Names[k]);
+                    db.TemplateParams.pushSubstitutionIntoPack(db.Names[k]);
+                t = t1;
+            }
+            else
+            {
+                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;
             }
-            t = t1;
         }
         if (begin_idx > db.Names.size())
             return first;
@@ -5218,9 +5292,7 @@
                     {
                         db.Names.back() = db.make<QualifiedName>(
                             db.Names.back(), name);
-                        db.Subs.push_back(
-                            Db::sub_type(1, db.Names.back(),
-                                         db.Names.get_allocator()));
+                        db.Subs.pushSubstitution(db.Names.back());
                     }
                     else
                         db.Names.back() = name;
@@ -5243,7 +5315,7 @@
                             db.make<QualifiedName>(db.Names.back(), name);
                     else
                         db.Names.back() = name;
-                    db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                    db.Subs.pushSubstitution(db.Names.back());
                     pop_subs = true;
                     t0 = t1;
                 }
@@ -5265,7 +5337,7 @@
                             db.make<QualifiedName>(db.Names.back(), name);
                     else
                         db.Names.back() = name;
-                    db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                    db.Subs.pushSubstitution(db.Names.back());
                     pop_subs = true;
                     t0 = t1;
                 }
@@ -5282,8 +5354,7 @@
                     db.Names.pop_back();
                     db.Names.back() = db.make<NameWithTemplateArgs>(
                         db.Names.back(), name);
-                    db.Subs.push_back(Db::sub_type(
-                        1, db.Names.back(), db.Names.get_allocator()));
+                    db.Subs.pushSubstitution(db.Names.back());
                     t0 = t1;
                     component_ends_with_template_args = true;
                 }
@@ -5308,7 +5379,7 @@
                             db.make<QualifiedName>(db.Names.back(), name);
                     else
                         db.Names.back() = name;
-                    db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                    db.Subs.pushSubstitution(db.Names.back());
                     pop_subs = true;
                     t0 = t1;
                 }
@@ -5319,7 +5390,7 @@
         first = t0 + 1;
         db.CV = cv;
         if (pop_subs && !db.Subs.empty())
-            db.Subs.pop_back();
+            db.Subs.popPack();
         if (ends_with_template_args)
             *ends_with_template_args = component_ends_with_template_args;
     }
@@ -5484,7 +5555,7 @@
                 {
                     if (db.Names.empty())
                         return first;
-                    db.Subs.push_back(Db::sub_type(1, db.Names.back(), db.Names.get_allocator()));
+                    db.Subs.pushSubstitution(db.Names.back());
                     t0 = t1;
                     t1 = parse_template_args(t0, last, db);
                     if (t1 != t0)
@@ -6035,16 +6106,14 @@
     }
 
     size_t internal_size = buf != nullptr ? *n : 0;
-    arena<bs> a;
-    Db db(a);
-    db.TemplateParams.emplace_back(a);
+    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.TemplateParams.front().empty())
+        !db.TemplateParams.empty())
     {
         db.FixForwardReferences = false;
         db.TagTemplates = false;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to