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