[libcxxabi] r309340 - [demangler] Use an AST to represent demangled names
Erik Pilkington via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 6 13:50:24 PDT 2017
Fixed in r310226, thanks!
On 8/4/17 12:08 PM, Kostya Serebryany wrote:
> and one more:
> https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2837
> Crash Type: Heap-buffer-overflow READ 8
> Crash Address: 0x615000000078
> Crash State:
> __cxxabiv1::parse_new_expr
> __cxxabiv1::parse_expression
> __cxxabiv1::parse_array_type
>
> On Mon, Jul 31, 2017 at 9:56 AM, Kostya Serebryany <kcc at google.com
> <mailto:kcc at google.com>> wrote:
>
> Yep, confirmed. Thanks!
> In the meantime, two new bugs popped up (probably, got un-hidden
> after your fixes):
> https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2804
> <https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2804>
> Crash Type: Heap-buffer-overflow READ 8
> Crash Address: 0x619000000078
> Crash State:
> __cxxabiv1::parse_encoding
> __cxxabiv1::demangle
> __cxa_demangle
>
> https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2800
> <https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2800>
> Crash Type: Out-of-memory (exceeds 2048 MB)
>
> Two older stack overflow bugs also remain.
>
> --kcc
>
> On Sun, Jul 30, 2017 at 1:12 PM, Erik Pilkington
> <erik.pilkington at gmail.com <mailto:erik.pilkington at gmail.com>> wrote:
>
> r309520 should fix the new failures. I'll keep an eye on
> oss-fuzz in case anything new comes up.
> Thanks for pinging me,
> Erik
>
> On 7/28/17 10:06 AM, Kostya Serebryany wrote:
>> Erik,
>> A bunch of old bugs reported in this code by OSS-Fuzz got
>> auto-closed today, thanks!
>>
>> Also a few new bugs got opened tonight, most likely caused by
>> this patch. You are auto-CC-ed.
>> I would start from
>> https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2767
>> <https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2767>
>> Crash Type: Null-dereference READ Crash Address:
>> 0x000000000008 Crash State: __cxxabiv1::parse_nested_name
>> __cxxabiv1::parse_name __cxxabiv1::parse_local_name
>> Also, you have the access to all inputs generated by the demangler fuzzer in a few months of fuzzing.
>> You can use that corpus for local testing, and I would also encourage you to add the corpus to the public LLVM bots.
>> --kcc
>>
>> On Thu, Jul 27, 2017 at 5:43 PM, Erik Pilkington via
>> cfe-commits <cfe-commits at lists.llvm.org
>> <mailto:cfe-commits at lists.llvm.org>> wrote:
>>
>> Author: epilk
>> Date: Thu Jul 27 17:43:49 2017
>> New Revision: 309340
>>
>> URL:
>> http://llvm.org/viewvc/llvm-project?rev=309340&view=rev
>> <http://llvm.org/viewvc/llvm-project?rev=309340&view=rev>
>> Log:
>> [demangler] Use an AST to represent demangled names
>>
>> The demangler now demangles by producing an AST, then
>> traverses that
>> AST to produce a demangled name. This is done for
>> performance reasons,
>> now the demangler doesn't manuiplate std::strings, which hurt
>> performance and caused string operations to be inlined
>> into the
>> parser, leading to large code size and stack usage.
>>
>> Differential revision: https://reviews.llvm.org/D35159
>> <https://reviews.llvm.org/D35159>
>>
>> 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=309340&r1=309339&r2=309340&view=diff
>> <http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp?rev=309340&r1=309339&r2=309340&view=diff>
>> ==============================================================================
>> --- libcxxabi/trunk/src/cxa_demangle.cpp (original)
>> +++ libcxxabi/trunk/src/cxa_demangle.cpp Thu Jul 27
>> 17:43:49 2017
>> @@ -13,7 +13,6 @@
>>
>> #include <vector>
>> #include <algorithm>
>> -#include <string>
>> #include <numeric>
>> #include <cstdlib>
>> #include <cstring>
>> @@ -41,6 +40,1370 @@ enum
>> success
>> };
>>
>> +class StringView {
>> + const char *First;
>> + const char *Last;
>> +
>> +public:
>> + template <size_t N>
>> + StringView(const char (&Str)[N]) : First(Str),
>> Last(Str + N - 1) {}
>> + StringView(const char *First, const char *Last) :
>> First(First), Last(Last) {}
>> + StringView() : First(nullptr), Last(nullptr) {}
>> +
>> + StringView substr(size_t From, size_t To) {
>> + if (To >= size())
>> + To = size() - 1;
>> + if (From >= size())
>> + From = size() - 1;
>> + return StringView(First + From, First + To);
>> + }
>> +
>> + StringView dropFront(size_t N) const {
>> + if (N >= size())
>> + N = size() - 1;
>> + return StringView(First + N, Last);
>> + }
>> +
>> + bool startsWith(StringView Str) const {
>> + if (Str.size() > size())
>> + return false;
>> + return std::equal(Str.begin(), Str.end(), begin());
>> + }
>> +
>> + const char &operator[](size_t Idx) const { return
>> *(begin() + Idx); }
>> +
>> + const char *begin() const { return First; }
>> + const char *end() const { return Last; }
>> + size_t size() const { return static_cast<size_t>(Last
>> - First); }
>> +};
>> +
>> +bool operator==(const StringView &LHS, const StringView
>> &RHS) {
>> + return LHS.size() == RHS.size() &&
>> + std::equal(LHS.begin(), LHS.end(), RHS.begin());
>> +}
>> +
>> +// Stream that AST nodes write their string
>> representation into after the AST
>> +// has been parsed.
>> +class OutputStream {
>> + char *Buffer;
>> + size_t CurrentPosition;
>> + size_t BufferCapacity;
>> +
>> + // Ensure there is at least n more positions in buffer.
>> + void grow(size_t N) {
>> + if (N + CurrentPosition >= BufferCapacity) {
>> + BufferCapacity *= 2;
>> + if (BufferCapacity < N + CurrentPosition)
>> + BufferCapacity = N + CurrentPosition;
>> + Buffer = static_cast<char *>(std::realloc(Buffer,
>> BufferCapacity));
>> + }
>> + }
>> +
>> +public:
>> + OutputStream(char *StartBuf, size_t Size)
>> + : Buffer(StartBuf), CurrentPosition(0),
>> BufferCapacity(Size) {}
>> +
>> + OutputStream &operator+=(StringView R) {
>> + size_t Size = R.size();
>> + if (Size == 0)
>> + return *this;
>> + grow(Size);
>> + memmove(Buffer + CurrentPosition, R.begin(), Size);
>> + CurrentPosition += Size;
>> + return *this;
>> + }
>> +
>> + OutputStream &operator+=(char C) {
>> + grow(1);
>> + Buffer[CurrentPosition++] = C;
>> + return *this;
>> + }
>> +
>> + // Offset of position in buffer, used for building
>> stream_string_view.
>> + typedef unsigned StreamPosition;
>> +
>> + // StringView into a stream, used for caching the ast
>> nodes.
>> + class StreamStringView {
>> + StreamPosition First, Last;
>> +
>> + friend class OutputStream;
>> +
>> + public:
>> + StreamStringView() : First(0), Last(0) {}
>> +
>> + StreamStringView(StreamPosition First,
>> StreamPosition Last)
>> + : First(First), Last(Last) {}
>> +
>> + bool empty() const { return First == Last; }
>> + };
>> +
>> + OutputStream &operator+=(StreamStringView &s) {
>> + size_t Sz = static_cast<size_t>(s.Last - s.First);
>> + if (Sz == 0)
>> + return *this;
>> + grow(Sz);
>> + memmove(Buffer + CurrentPosition, Buffer + s.First, Sz);
>> + CurrentPosition += Sz;
>> + return *this;
>> + }
>> +
>> + StreamPosition getCurrentPosition() const {
>> + return static_cast<StreamPosition>(CurrentPosition);
>> + }
>> +
>> + StreamStringView
>> makeStringViewFromPastPosition(StreamPosition Pos) {
>> + return StreamStringView(Pos, getCurrentPosition());
>> + }
>> +
>> + char back() const {
>> + return CurrentPosition ? Buffer[CurrentPosition - 1]
>> : '\0';
>> + }
>> +
>> + bool empty() const { return CurrentPosition == 0; }
>> +
>> + char *getBuffer() { return Buffer; }
>> + char *getBufferEnd() { return Buffer + CurrentPosition
>> - 1; }
>> + size_t getBufferCapacity() { return BufferCapacity; }
>> +};
>> +
>> +// Base class of all AST nodes. The AST is built by the
>> parser, then is
>> +// traversed by the printLeft/Right functions to produce
>> a demangled string.
>> +class Node {
>> +public:
>> + enum Kind : unsigned char {
>> + KDotSuffix,
>> + KVendorExtQualType,
>> + KQualType,
>> + KConversionOperatorType,
>> + KPostfixQualifiedType,
>> + KNameType,
>> + KObjCProtoName,
>> + KPointerType,
>> + KLValueReferenceType,
>> + KRValueReferenceType,
>> + KPointerToMemberType,
>> + KArrayType,
>> + KFunctionType,
>> + KTopLevelFunctionDecl,
>> + KFunctionQualType,
>> + KFunctionRefQualType,
>> + KLiteralOperator,
>> + KSpecialName,
>> + KCtorVtableSpecialName,
>> + KQualifiedName,
>> + KEmptyName,
>> + KVectorType,
>> + KTemplateParams,
>> + KNameWithTemplateArgs,
>> + KGlobalQualifiedName,
>> + KStdQualifiedName,
>> + KExpandedSpecialSubstitution,
>> + KSpecialSubstitution,
>> + KCtorDtorName,
>> + KDtorName,
>> + KUnnamedTypeName,
>> + KLambdaTypeName,
>> + KExpr,
>> + };
>> +
>> + const Kind K;
>> +
>> +private:
>> + // If this Node has any RHS part, potentally many
>> Nodes further down.
>> + const unsigned HasRHSComponent : 1;
>> + const unsigned HasFunction : 1;
>> + const unsigned HasArray : 1;
>> +
>> +public:
>> + Node(Kind K, bool HasRHS = false, bool HasFunction =
>> false,
>> + bool HasArray = false)
>> + : K(K), HasRHSComponent(HasRHS),
>> HasFunction(HasFunction),
>> + HasArray(HasArray) {}
>> +
>> + bool hasRHSComponent() const { return HasRHSComponent; }
>> + bool hasArray() const { return HasArray; }
>> + bool hasFunction() const { return HasFunction; }
>> +
>> + void print(OutputStream &s) const {
>> + printLeft(s);
>> + if (hasRHSComponent())
>> + printRight(s);
>> + }
>> +
>> + // Print the "left" side of this Node into OutputStream.
>> + virtual void printLeft(OutputStream &) const = 0;
>> +
>> + // Print the "right". This distinction is necessary to
>> represent C++ types
>> + // that appear on the RHS of their subtype, such as
>> arrays or functions.
>> + // Since most types don't have such a component,
>> provide a default
>> + // implemenation.
>> + virtual void printRight(OutputStream &) const {}
>> +
>> + virtual StringView getBaseName() const { return
>> StringView(); }
>> +
>> + // Silence compiler warnings, this dtor will never be
>> called.
>> + virtual ~Node() = default;
>> +};
>> +
>> +class NodeArray {
>> + Node **Elements;
>> + size_t NumElements;
>> +
>> +public:
>> + NodeArray() : NumElements(0) {}
>> + NodeArray(Node **Elements, size_t NumElements)
>> + : Elements(Elements), NumElements(NumElements) {}
>> +
>> + bool empty() const { return NumElements == 0; }
>> + size_t size() const { return NumElements; }
>> +
>> + void printWithSeperator(OutputStream &S, StringView
>> Seperator) const {
>> + for (size_t Idx = 0; Idx != NumElements; ++Idx) {
>> + if (Idx)
>> + S += Seperator;
>> + Elements[Idx]->print(S);
>> + }
>> + }
>> +};
>> +
>> +class DotSuffix final : public Node {
>> + const Node *Prefix;
>> + const StringView Suffix;
>> +
>> +public:
>> + DotSuffix(Node *Prefix, StringView Suffix)
>> + : Node(KDotSuffix), Prefix(Prefix), Suffix(Suffix) {}
>> +
>> + void printLeft(OutputStream &s) const override {
>> + Prefix->print(s);
>> + s += " (";
>> + s += Suffix;
>> + s += ")";
>> + }
>> +};
>> +
>> +class VendorExtQualType final : public Node {
>> + const Node *Ext;
>> + const Node *Ty;
>> +
>> +public:
>> + VendorExtQualType(Node *Ext, Node *Ty)
>> + : Node(KVendorExtQualType), Ext(Ext), Ty(Ty) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + Ext->print(S);
>> + S += " ";
>> + Ty->printLeft(S);
>> + }
>> +
>> + void printRight(OutputStream &S) const override {
>> Ty->printRight(S); }
>> +};
>> +
>> +enum Qualifiers {
>> + QualNone = 0,
>> + QualConst = 0x1,
>> + QualVolatile = 0x2,
>> + QualRestrict = 0x4,
>> +};
>> +
>> +void addQualifiers(Qualifiers &Q1, Qualifiers Q2) {
>> + Q1 = static_cast<Qualifiers>(Q1 | Q2);
>> +}
>> +
>> +class QualType : public Node {
>> +protected:
>> + const Qualifiers Quals;
>> + const Node *Child;
>> +
>> + void printQuals(OutputStream &S) const {
>> + if (Quals & QualConst)
>> + S += " const";
>> + if (Quals & QualVolatile)
>> + S += " volatile";
>> + if (Quals & QualRestrict)
>> + S += " restrict";
>> + }
>> +
>> +public:
>> + QualType(Node *Child, Qualifiers Quals)
>> + : Node(KQualType, Child->hasRHSComponent(),
>> Child->hasFunction(),
>> + Child->hasArray()),
>> + Quals(Quals), Child(Child) {}
>> +
>> + QualType(Node::Kind ChildKind, Node *Child, Qualifiers
>> Quals)
>> + : Node(ChildKind, Child->hasRHSComponent(),
>> Child->hasFunction(),
>> + Child->hasArray()),
>> + Quals(Quals), Child(Child) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + Child->printLeft(S);
>> + printQuals(S);
>> + }
>> +
>> + void printRight(OutputStream &S) const override {
>> Child->printRight(S); }
>> +};
>> +
>> +class ConversionOperatorType final : public Node {
>> + const Node *Ty;
>> +
>> +public:
>> + ConversionOperatorType(Node *Ty) :
>> Node(KConversionOperatorType), Ty(Ty) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "operator ";
>> + Ty->print(S);
>> + }
>> +};
>> +
>> +class PostfixQualifiedType final : public Node {
>> + const Node *Ty;
>> + const StringView Postfix;
>> +
>> +public:
>> + PostfixQualifiedType(Node *Ty, StringView Postfix)
>> + : Node(KPostfixQualifiedType), Ty(Ty),
>> Postfix(Postfix) {}
>> +
>> + void printLeft(OutputStream &s) const override {
>> + Ty->printLeft(s);
>> + s += Postfix;
>> + }
>> +
>> + void printRight(OutputStream &S) const override {
>> Ty->printRight(S); }
>> +};
>> +
>> +class NameType final : public Node {
>> + const StringView Name;
>> +
>> +public:
>> + NameType(StringView Name) : Node(KNameType), Name(Name) {}
>> +
>> + StringView getName() const { return Name; }
>> + StringView getBaseName() const override { return Name; }
>> +
>> + void printLeft(OutputStream &s) const override { s +=
>> Name; }
>> +};
>> +
>> +class ObjCProtoName : public Node {
>> + Node *Ty;
>> + Node *Protocol;
>> +
>> + friend class PointerType;
>> +
>> +public:
>> + ObjCProtoName(Node *Ty, Node *Protocol)
>> + : Node(KObjCProtoName), Ty(Ty), Protocol(Protocol) {}
>> +
>> + bool isObjCObject() const {
>> + return Ty->K == KNameType &&
>> + static_cast<NameType *>(Ty)->getName() ==
>> "objc_object";
>> + }
>> +
>> + void printLeft(OutputStream &S) const override {
>> + Ty->printLeft(S);
>> + S += "<";
>> + Protocol->printLeft(S);
>> + S += ">";
>> + }
>> +};
>> +
>> +class PointerType final : public Node {
>> + const Node *Pointee;
>> +
>> +public:
>> + PointerType(Node *Pointee)
>> + : Node(KPointerType, Pointee->hasRHSComponent()),
>> Pointee(Pointee) {}
>> +
>> + void printLeft(OutputStream &s) const override {
>> + // We rewrite objc_object<SomeProtocol>* into
>> id<SomeProtocol>.
>> + if (Pointee->K != KObjCProtoName ||
>> + !static_cast<const ObjCProtoName
>> *>(Pointee)->isObjCObject()) {
>> + Pointee->printLeft(s);
>> + if (Pointee->hasArray())
>> + s += " ";
>> + if (Pointee->hasArray() || Pointee->hasFunction())
>> + s += "(";
>> + s += "*";
>> + } else {
>> + const auto *objcProto = static_cast<const
>> ObjCProtoName *>(Pointee);
>> + s += "id<";
>> + objcProto->Protocol->print(s);
>> + s += ">";
>> + }
>> + }
>> +
>> + void printRight(OutputStream &s) const override {
>> + if (Pointee->K != KObjCProtoName ||
>> + !static_cast<const ObjCProtoName
>> *>(Pointee)->isObjCObject()) {
>> + if (Pointee->hasArray() || Pointee->hasFunction())
>> + s += ")";
>> + Pointee->printRight(s);
>> + }
>> + }
>> +};
>> +
>> +class LValueReferenceType final : public Node {
>> + const Node *Pointee;
>> +
>> +public:
>> + LValueReferenceType(Node *Pointee)
>> + : Node(KLValueReferenceType,
>> Pointee->hasRHSComponent()),
>> + Pointee(Pointee) {}
>> +
>> + void printLeft(OutputStream &s) const override {
>> + Pointee->printLeft(s);
>> + if (Pointee->hasArray())
>> + s += " ";
>> + if (Pointee->hasArray() || Pointee->hasFunction())
>> + s += "(&";
>> + else
>> + s += "&";
>> + }
>> + void printRight(OutputStream &s) const override {
>> + if (Pointee->hasArray() || Pointee->hasFunction())
>> + s += ")";
>> + Pointee->printRight(s);
>> + }
>> +};
>> +
>> +class RValueReferenceType final : public Node {
>> + const Node *Pointee;
>> +
>> +public:
>> + RValueReferenceType(Node *Pointee)
>> + : Node(KRValueReferenceType,
>> Pointee->hasRHSComponent()),
>> + Pointee(Pointee) {}
>> +
>> + void printLeft(OutputStream &s) const override {
>> + Pointee->printLeft(s);
>> + if (Pointee->hasArray())
>> + s += " ";
>> + if (Pointee->hasArray() || Pointee->hasFunction())
>> + s += "(&&";
>> + else
>> + s += "&&";
>> + }
>> +
>> + void printRight(OutputStream &s) const override {
>> + if (Pointee->hasArray() || Pointee->hasFunction())
>> + s += ")";
>> + Pointee->printRight(s);
>> + }
>> +};
>> +
>> +class PointerToMemberType final : public Node {
>> + const Node *ClassType;
>> + const Node *MemberType;
>> +
>> +public:
>> + PointerToMemberType(Node *ClassType, Node *MemberType)
>> + : Node(KPointerToMemberType,
>> MemberType->hasRHSComponent()),
>> + ClassType(ClassType), MemberType(MemberType) {}
>> +
>> + void printLeft(OutputStream &s) const override {
>> + MemberType->printLeft(s);
>> + if (MemberType->hasArray() || MemberType->hasFunction())
>> + s += "(";
>> + else
>> + s += " ";
>> + ClassType->print(s);
>> + s += "::*";
>> + }
>> +
>> + void printRight(OutputStream &s) const override {
>> + if (MemberType->hasArray() || MemberType->hasFunction())
>> + s += ")";
>> + MemberType->printRight(s);
>> + }
>> +};
>> +
>> +class NodeOrString {
>> + const void *First;
>> + const void *Second;
>> +
>> +public:
>> + /* implicit */ NodeOrString(StringView Str) {
>> + const char *FirstChar = Str.begin();
>> + const char *SecondChar = Str.end();
>> + if (SecondChar == nullptr) {
>> + assert(FirstChar == SecondChar);
>> + ++FirstChar, ++SecondChar;
>> + }
>> + First = static_cast<const void *>(FirstChar);
>> + Second = static_cast<const void *>(SecondChar);
>> + }
>> +
>> + /* implicit */ NodeOrString(Node *N)
>> + : First(static_cast<const void *>(N)),
>> Second(nullptr) {}
>> + NodeOrString() : First(nullptr), Second(nullptr) {}
>> +
>> + bool isString() const { return Second && First; }
>> + bool isNode() const { return First && !Second; }
>> + bool isEmpty() const { return !First && !Second; }
>> +
>> + StringView asString() const {
>> + assert(isString());
>> + return StringView(static_cast<const char *>(First),
>> + static_cast<const char *>(Second));
>> + }
>> +
>> + const Node *asNode() const {
>> + assert(isNode());
>> + return static_cast<const Node *>(First);
>> + }
>> +};
>> +
>> +class ArrayType final : public Node {
>> + Node *Base;
>> + NodeOrString Dimension;
>> +
>> +public:
>> + ArrayType(Node *Base, NodeOrString Dimension)
>> + : Node(KArrayType, true, false, true), Base(Base),
>> Dimension(Dimension) {}
>> +
>> + // Incomplete array type.
>> + ArrayType(Node *Base) : Node(KArrayType, true, false,
>> true), Base(Base) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> Base->printLeft(S); }
>> +
>> + void printRight(OutputStream &S) const override {
>> + if (S.back() != ']')
>> + S += " ";
>> + S += "[";
>> + if (Dimension.isString())
>> + S += Dimension.asString();
>> + else if (Dimension.isNode())
>> + Dimension.asNode()->print(S);
>> + S += "]";
>> + Base->printRight(S);
>> + }
>> +};
>> +
>> +class FunctionType final : public Node {
>> + Node *Ret;
>> + NodeArray Params;
>> +
>> +public:
>> + FunctionType(Node *Ret, NodeArray Params)
>> + : Node(KFunctionType, true, true), Ret(Ret),
>> Params(Params) {}
>> +
>> + // Handle C++'s ... quirky decl grammer by using the
>> left & right
>> + // distinction. Consider:
>> + // int (*f(float))(char) {}
>> + // f is a function that takes a float and returns a
>> pointer to a function
>> + // that takes a char and returns an int. If we're
>> trying to print f, start
>> + // by printing out the return types's left, then print
>> our parameters, then
>> + // finally print right of the return type.
>> + void printLeft(OutputStream &S) const override {
>> + Ret->printLeft(S);
>> + S += " ";
>> + }
>> +
>> + void printRight(OutputStream &S) const override {
>> + S += "(";
>> + Params.printWithSeperator(S, ", ");
>> + S += ")";
>> + Ret->printRight(S);
>> + }
>> +};
>> +
>> +class TopLevelFunctionDecl final : public Node {
>> + const Node *Ret;
>> + const Node *Name;
>> + NodeArray Params;
>> +
>> +public:
>> + TopLevelFunctionDecl(Node *Ret, Node *Name, NodeArray
>> Params)
>> + : Node(KTopLevelFunctionDecl, true, true),
>> Ret(Ret), Name(Name),
>> + Params(Params) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + if (Ret) {
>> + Ret->printLeft(S);
>> + if (!Ret->hasRHSComponent())
>> + S += " ";
>> + }
>> + Name->print(S);
>> + }
>> +
>> + void printRight(OutputStream &S) const override {
>> + S += "(";
>> + Params.printWithSeperator(S, ", ");
>> + S += ")";
>> + if (Ret)
>> + Ret->printRight(S);
>> + }
>> +};
>> +
>> +enum FunctionRefQual : unsigned char {
>> + FrefQualNone,
>> + FrefQualLValue,
>> + FrefQualRValue,
>> +};
>> +
>> +class FunctionRefQualType : public Node {
>> + Node *Fn;
>> + FunctionRefQual Quals;
>> +
>> + friend class FunctionQualType;
>> +
>> +public:
>> + FunctionRefQualType(Node *Fn, FunctionRefQual Quals)
>> + : Node(KFunctionRefQualType, true, true), Fn(Fn),
>> Quals(Quals) {}
>> +
>> + void printQuals(OutputStream &S) const {
>> + if (Quals == FrefQualLValue)
>> + S += " &";
>> + else
>> + S += " &&";
>> + }
>> +
>> + void printLeft(OutputStream &S) const override {
>> Fn->printLeft(S); }
>> +
>> + void printRight(OutputStream &S) const override {
>> + Fn->printRight(S);
>> + printQuals(S);
>> + }
>> +};
>> +
>> +class FunctionQualType final : public QualType {
>> +public:
>> + FunctionQualType(Node *Child, Qualifiers Quals)
>> + : QualType(KFunctionQualType, Child, Quals) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> Child->printLeft(S); }
>> +
>> + void printRight(OutputStream &S) const override {
>> + if (Child->K == KFunctionRefQualType) {
>> + auto *RefQuals = static_cast<const
>> FunctionRefQualType *>(Child);
>> + RefQuals->Fn->printRight(S);
>> + printQuals(S);
>> + RefQuals->printQuals(S);
>> + } else {
>> + Child->printRight(S);
>> + printQuals(S);
>> + }
>> + }
>> +};
>> +
>> +class LiteralOperator : public Node {
>> + const Node *OpName;
>> +
>> +public:
>> + LiteralOperator(Node *OpName) :
>> Node(KLiteralOperator), OpName(OpName) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "operator\"\" ";
>> + OpName->print(S);
>> + }
>> +};
>> +
>> +class SpecialName final : public Node {
>> + const StringView Special;
>> + const Node *Child;
>> +
>> +public:
>> + SpecialName(StringView Special, Node *Child)
>> + : Node(KSpecialName), Special(Special),
>> Child(Child) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += Special;
>> + Child->print(S);
>> + }
>> +};
>> +
>> +class CtorVtableSpecialName final : public Node {
>> + const Node *FirstType;
>> + const Node *SecondType;
>> +
>> +public:
>> + CtorVtableSpecialName(Node *FirstType, Node *SecondType)
>> + : Node(KCtorVtableSpecialName), FirstType(FirstType),
>> + SecondType(SecondType) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "construction vtable for ";
>> + FirstType->print(S);
>> + S += "-in-";
>> + SecondType->print(S);
>> + }
>> +};
>> +
>> +class QualifiedName final : public Node {
>> + // qualifier::name
>> + const Node *Qualifier;
>> + const Node *Name;
>> +
>> + mutable OutputStream::StreamStringView Cache;
>> +
>> +public:
>> + QualifiedName(Node *Qualifier, Node *Name)
>> + : Node(KQualifiedName), Qualifier(Qualifier),
>> Name(Name) {}
>> +
>> + StringView getBaseName() const override { return
>> Name->getBaseName(); }
>> +
>> + void printLeft(OutputStream &S) const override {
>> + if (!Cache.empty()) {
>> + S += Cache;
>> + return;
>> + }
>> +
>> + OutputStream::StreamPosition Start =
>> S.getCurrentPosition();
>> + if (Qualifier->K != KEmptyName) {
>> + Qualifier->print(S);
>> + S += "::";
>> + }
>> + Name->print(S);
>> + Cache = S.makeStringViewFromPastPosition(Start);
>> + }
>> +};
>> +
>> +class EmptyName : public Node {
>> +public:
>> + EmptyName() : Node(KEmptyName) {}
>> + void printLeft(OutputStream &) const override {}
>> +};
>> +
>> +class VectorType final : public Node {
>> + const Node *BaseType;
>> + const NodeOrString Dimension;
>> + const bool IsPixel;
>> +
>> +public:
>> + VectorType(NodeOrString Dimension)
>> + : Node(KVectorType), BaseType(nullptr),
>> Dimension(Dimension),
>> + IsPixel(true) {}
>> + VectorType(Node *BaseType, NodeOrString Dimension)
>> + : Node(KVectorType), BaseType(BaseType),
>> Dimension(Dimension),
>> + IsPixel(false) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + if (IsPixel) {
>> + S += "pixel vector[";
>> + S += Dimension.asString();
>> + S += "]";
>> + } else {
>> + BaseType->print(S);
>> + S += " vector[";
>> + if (Dimension.isNode())
>> + Dimension.asNode()->print(S);
>> + else if (Dimension.isString())
>> + S += Dimension.asString();
>> + S += "]";
>> + }
>> + }
>> +};
>> +
>> +class TemplateParams final : public Node {
>> + NodeArray Params;
>> +
>> + mutable OutputStream::StreamStringView Cache;
>> +
>> +public:
>> + TemplateParams(NodeArray Params) :
>> Node(KTemplateParams), Params(Params) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + if (!Cache.empty()) {
>> + S += Cache;
>> + return;
>> + }
>> +
>> + OutputStream::StreamPosition Start =
>> S.getCurrentPosition();
>> +
>> + S += "<";
>> + Params.printWithSeperator(S, ", ");
>> + if (S.back() == '>')
>> + S += " ";
>> + S += ">";
>> +
>> + Cache = S.makeStringViewFromPastPosition(Start);
>> + }
>> +};
>> +
>> +class NameWithTemplateArgs final : public Node {
>> + // name<template_args>
>> + Node *Name;
>> + Node *TemplateArgs;
>> +
>> +public:
>> + NameWithTemplateArgs(Node *Name, Node *TemplateArgs)
>> + : Node(KNameWithTemplateArgs), Name(Name),
>> TemplateArgs(TemplateArgs) {}
>> +
>> + StringView getBaseName() const override { return
>> Name->getBaseName(); }
>> +
>> + void printLeft(OutputStream &S) const override {
>> + Name->print(S);
>> + TemplateArgs->print(S);
>> + }
>> +};
>> +
>> +class GlobalQualifiedName final : public Node {
>> + Node *Child;
>> +
>> +public:
>> + GlobalQualifiedName(Node *Child) :
>> Node(KGlobalQualifiedName), Child(Child) {}
>> +
>> + StringView getBaseName() const override { return
>> Child->getBaseName(); }
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "::";
>> + Child->print(S);
>> + }
>> +};
>> +
>> +class StdQualifiedName final : public Node {
>> + Node *Child;
>> +
>> +public:
>> + StdQualifiedName(Node *Child) :
>> Node(KStdQualifiedName), Child(Child) {}
>> +
>> + StringView getBaseName() const override { return
>> Child->getBaseName(); }
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "std::";
>> + Child->print(S);
>> + }
>> +};
>> +
>> +enum class SpecialSubKind {
>> + allocator,
>> + basic_string,
>> + string,
>> + istream,
>> + ostream,
>> + iostream,
>> +};
>> +
>> +class ExpandedSpecialSubstitution final : public Node {
>> + SpecialSubKind SSK;
>> +
>> +public:
>> + ExpandedSpecialSubstitution(SpecialSubKind SSK)
>> + : Node(KExpandedSpecialSubstitution), SSK(SSK) {}
>> +
>> + StringView getBaseName() const override {
>> + switch (SSK) {
>> + case SpecialSubKind::allocator:
>> + return StringView("allocator");
>> + case SpecialSubKind::basic_string:
>> + return StringView("basic_string");
>> + case SpecialSubKind::string:
>> + return StringView("basic_string");
>> + case SpecialSubKind::istream:
>> + return StringView("basic_istream");
>> + case SpecialSubKind::ostream:
>> + return StringView("basic_ostream");
>> + case SpecialSubKind::iostream:
>> + return StringView("basic_iostream");
>> + }
>> + }
>> +
>> + void printLeft(OutputStream &S) const override {
>> + switch (SSK) {
>> + case SpecialSubKind::allocator:
>> + S += "std::basic_string<char,
>> std::char_traits<char>, "
>> + "std::allocator<char> >";
>> + break;
>> + case SpecialSubKind::basic_string:
>> + case SpecialSubKind::string:
>> + S += "std::basic_string<char,
>> std::char_traits<char>, "
>> + "std::allocator<char> >";
>> + break;
>> + case SpecialSubKind::istream:
>> + S += "std::basic_istream<char,
>> std::char_traits<char> >";
>> + break;
>> + case SpecialSubKind::ostream:
>> + S += "std::basic_ostream<char,
>> std::char_traits<char> >";
>> + break;
>> + case SpecialSubKind::iostream:
>> + S += "std::basic_iostream<char,
>> std::char_traits<char> >";
>> + break;
>> + }
>> + }
>> +};
>> +
>> +class SpecialSubstitution final : public Node {
>> +public:
>> + SpecialSubKind SSK;
>> +
>> + SpecialSubstitution(SpecialSubKind SSK)
>> + : Node(KSpecialSubstitution), SSK(SSK) {}
>> +
>> + StringView getBaseName() const override {
>> + switch (SSK) {
>> + case SpecialSubKind::allocator:
>> + return StringView("allocator");
>> + case SpecialSubKind::basic_string:
>> + return StringView("basic_string");
>> + case SpecialSubKind::string:
>> + return StringView("string");
>> + case SpecialSubKind::istream:
>> + return StringView("istream");
>> + case SpecialSubKind::ostream:
>> + return StringView("ostream");
>> + case SpecialSubKind::iostream:
>> + return StringView("iostream");
>> + }
>> + }
>> +
>> + void printLeft(OutputStream &S) const override {
>> + switch (SSK) {
>> + case SpecialSubKind::allocator:
>> + S += "std::allocator";
>> + break;
>> + case SpecialSubKind::basic_string:
>> + S += "std::basic_string";
>> + break;
>> + case SpecialSubKind::string:
>> + S += "std::string";
>> + break;
>> + case SpecialSubKind::istream:
>> + S += "std::istream";
>> + break;
>> + case SpecialSubKind::ostream:
>> + S += "std::ostream";
>> + break;
>> + case SpecialSubKind::iostream:
>> + S += "std::iostream";
>> + break;
>> + }
>> + }
>> +};
>> +
>> +class CtorDtorName final : public Node {
>> + const Node *Basename;
>> + const bool IsDtor;
>> +
>> +public:
>> + CtorDtorName(Node *Basename, bool IsDtor)
>> + : Node(KCtorDtorName), Basename(Basename),
>> IsDtor(IsDtor) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + if (IsDtor)
>> + S += "~";
>> + S += Basename->getBaseName();
>> + }
>> +};
>> +
>> +class DtorName : public Node {
>> + const Node *Base;
>> +
>> +public:
>> + DtorName(Node *Base) : Node(KDtorName), Base(Base) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "~";
>> + Base->printLeft(S);
>> + }
>> +};
>> +
>> +class UnnamedTypeName : public Node {
>> + const StringView Count;
>> +
>> +public:
>> + UnnamedTypeName(StringView Count) :
>> Node(KUnnamedTypeName), Count(Count) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "'unnamed";
>> + S += Count;
>> + S += "\'";
>> + }
>> +};
>> +
>> +class LambdaTypeName : public Node {
>> + NodeArray Params;
>> + StringView Count;
>> +
>> +public:
>> + LambdaTypeName(NodeArray Params, StringView Count)
>> + : Node(KLambdaTypeName), Params(Params),
>> Count(Count) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "\'lambda";
>> + S += Count;
>> + S += "\'(";
>> + Params.printWithSeperator(S, ", ");
>> + S += ")";
>> + }
>> +};
>> +
>> +// -- Expression Nodes --
>> +
>> +struct Expr : public Node {
>> + Expr() : Node(KExpr) {}
>> +};
>> +
>> +class BinaryExpr : public Expr {
>> + const Node *LHS;
>> + const StringView InfixOperator;
>> + const Node *RHS;
>> +
>> +public:
>> + BinaryExpr(Node *LHS, StringView InfixOperator, Node *RHS)
>> + : LHS(LHS), InfixOperator(InfixOperator), RHS(RHS) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + // might be a template argument expression, then we
>> need to disambiguate
>> + // with parens.
>> + if (InfixOperator == ">")
>> + S += "(";
>> +
>> + S += "(";
>> + LHS->print(S);
>> + S += ") ";
>> + S += InfixOperator;
>> + S += " (";
>> + RHS->print(S);
>> + S += ")";
>> +
>> + if (InfixOperator == ">")
>> + S += ")";
>> + }
>> +};
>> +
>> +class ArraySubscriptExpr : public Expr {
>> + const Node *Op1;
>> + const Node *Op2;
>> +
>> +public:
>> + ArraySubscriptExpr(Node *Op1, Node *Op2) : Op1(Op1),
>> Op2(Op2) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "(";
>> + Op1->print(S);
>> + S += ")[";
>> + Op2->print(S);
>> + S += "]";
>> + }
>> +};
>> +
>> +class PostfixExpr : public Expr {
>> + const Node *Child;
>> + const StringView Operand;
>> +
>> +public:
>> + PostfixExpr(Node *Child, StringView Operand)
>> + : Child(Child), Operand(Operand) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "(";
>> + Child->print(S);
>> + S += ")";
>> + S += Operand;
>> + }
>> +};
>> +
>> +class ConditionalExpr : public Expr {
>> + const Node *Cond;
>> + const Node *Then;
>> + const Node *Else;
>> +
>> +public:
>> + ConditionalExpr(Node *Cond, Node *Then, Node *Else)
>> + : Cond(Cond), Then(Then), Else(Else) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "(";
>> + Cond->print(S);
>> + S += ") ? (";
>> + Then->print(S);
>> + S += ") : (";
>> + Else->print(S);
>> + S += ")";
>> + }
>> +};
>> +
>> +class MemberExpr : public Expr {
>> + const Node *LHS;
>> + const StringView Kind;
>> + const Node *RHS;
>> +
>> +public:
>> + MemberExpr(Node *LHS, StringView Kind, Node *RHS)
>> + : LHS(LHS), Kind(Kind), RHS(RHS) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + LHS->print(S);
>> + S += Kind;
>> + RHS->print(S);
>> + }
>> +};
>> +
>> +class EnclosingExpr : public Expr {
>> + const StringView Prefix;
>> + const Node *Infix;
>> + const StringView Postfix;
>> +
>> +public:
>> + EnclosingExpr(StringView Prefix, Node *Infix,
>> StringView Postfix)
>> + : Prefix(Prefix), Infix(Infix), Postfix(Postfix) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += Prefix;
>> + Infix->print(S);
>> + S += Postfix;
>> + }
>> +};
>> +
>> +class CastExpr : public Expr {
>> + // cast_kind<to>(from)
>> + const StringView CastKind;
>> + const Node *To;
>> + const Node *From;
>> +
>> +public:
>> + CastExpr(StringView CastKind, Node *To, Node *From)
>> + : CastKind(CastKind), To(To), From(From) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += CastKind;
>> + S += "<";
>> + To->printLeft(S);
>> + S += ">(";
>> + From->printLeft(S);
>> + S += ")";
>> + }
>> +};
>> +
>> +class SizeofParamPackExpr : public Expr {
>> + NodeArray Args;
>> +
>> +public:
>> + SizeofParamPackExpr(NodeArray Args) : Args(Args) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "sizeof...(";
>> + Args.printWithSeperator(S, ", ");
>> + S += ")";
>> + }
>> +};
>> +
>> +class CallExpr : public Expr {
>> + const Node *Callee;
>> + NodeArray Args;
>> +
>> +public:
>> + CallExpr(Node *Callee, NodeArray Args) :
>> Callee(Callee), Args(Args) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + Callee->print(S);
>> + S += "(";
>> + Args.printWithSeperator(S, ", ");
>> + S += ")";
>> + }
>> +};
>> +
>> +class NewExpr : public Expr {
>> + // new (expr_list) type(init_list)
>> + NodeArray ExprList;
>> + Node *Type;
>> + NodeArray InitList;
>> + bool IsGlobal; // ::operator new ?
>> + bool IsArray; // new[] ?
>> +public:
>> + NewExpr(NodeArray ExprList, Node *Type, NodeArray
>> InitList, bool IsGlobal,
>> + bool IsArray)
>> + : ExprList(ExprList), Type(Type),
>> InitList(InitList), IsGlobal(IsGlobal),
>> + IsArray(IsArray) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + if (IsGlobal)
>> + S += "::operator ";
>> + S += "new";
>> + if (IsArray)
>> + S += "[]";
>> + if (!ExprList.empty()) {
>> + S += "(";
>> + ExprList.printWithSeperator(S, ", ");
>> + S += ")";
>> + }
>> + Type->print(S);
>> + if (!InitList.empty()) {
>> + S += "(";
>> + InitList.printWithSeperator(S, ", ");
>> + S += ")";
>> + }
>> + }
>> +};
>> +
>> +class DeleteExpr : public Expr {
>> + Node *Op;
>> + bool IsGlobal;
>> + bool IsArray;
>> +
>> +public:
>> + DeleteExpr(Node *Op, bool IsGlobal, bool IsArray)
>> + : Op(Op), IsGlobal(IsGlobal), IsArray(IsArray) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + if (IsGlobal)
>> + S += "::";
>> + S += "delete";
>> + if (IsArray)
>> + S += "[] ";
>> + Op->print(S);
>> + }
>> +};
>> +
>> +class PrefixExpr : public Expr {
>> + StringView Prefix;
>> + Node *Child;
>> +
>> +public:
>> + PrefixExpr(StringView Prefix, Node *Child) :
>> Prefix(Prefix), Child(Child) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += Prefix;
>> + S += "(";
>> + Child->print(S);
>> + S += ")";
>> + }
>> +};
>> +
>> +class FunctionParam : public Expr {
>> + StringView Number;
>> +
>> +public:
>> + FunctionParam(StringView Number) : Number(Number) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "fp";
>> + S += Number;
>> + }
>> +};
>> +
>> +class ExprList : public Expr {
>> + NodeArray SubExprs;
>> +
>> +public:
>> + ExprList(NodeArray SubExprs) : SubExprs(SubExprs) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "(";
>> + SubExprs.printWithSeperator(S, ", ");
>> + S += ")";
>> + }
>> +};
>> +
>> +class ConversionExpr : public Expr {
>> + NodeArray Expressions;
>> + NodeArray Types;
>> +
>> +public:
>> + ConversionExpr(NodeArray Expressions, NodeArray Types)
>> + : Expressions(Expressions), Types(Types) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "(";
>> + Expressions.printWithSeperator(S, ", ");
>> + S += ")(";
>> + Types.printWithSeperator(S, ", ");
>> + S += ")";
>> + }
>> +};
>> +
>> +class ThrowExpr : public Expr {
>> + const Node *Op;
>> +
>> +public:
>> + ThrowExpr(Node *Op) : Op(Op) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "throw ";
>> + Op->print(S);
>> + }
>> +};
>> +
>> +class BoolExpr : public Expr {
>> + bool Value;
>> +
>> +public:
>> + BoolExpr(bool Value) : Value(Value) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += Value ? StringView("true") : StringView("false");
>> + }
>> +};
>> +
>> +class IntegerCastExpr : public Expr {
>> + // ty(integer)
>> + Node *Ty;
>> + StringView Integer;
>> +
>> +public:
>> + IntegerCastExpr(Node *Ty, StringView Integer) :
>> Ty(Ty), Integer(Integer) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + S += "(";
>> + Ty->print(S);
>> + S += ")";
>> + S += Integer;
>> + }
>> +};
>> +
>> +class IntegerExpr : public Expr {
>> + StringView Type;
>> + StringView Value;
>> +
>> +public:
>> + IntegerExpr(StringView Type, StringView Value) :
>> Type(Type), Value(Value) {}
>> +
>> + void printLeft(OutputStream &S) const override {
>> + if (Type.size() > 3) {
>> + S += "(";
>> + S += Type;
>> + S += ")";
>> + }
>> +
>> + if (Value[0] == 'n') {
>> + S += "-";
>> + S += Value.dropFront(1);
>> + } else
>> + S += Value;
>> +
>> + if (Type.size() <= 3)
>> + S += Type;
>> + }
>> +};
>> +
>> +template <class Float> struct FloatData;
>> +
>> +template <class Float> class FloatExpr : public Expr {
>> + const StringView Contents;
>> +
>> +public:
>> + FloatExpr(StringView Contents) : Contents(Contents) {}
>> +
>> + void printLeft(OutputStream &s) const override {
>> + const char *first = Contents.begin();
>> + const char *last = Contents.end() + 1;
>> +
>> + const size_t N = FloatData<Float>::mangled_size;
>> + if (static_cast<std::size_t>(last - first) > N) {
>> + last = first + N;
>> + union {
>> + Float value;
>> + char buf[sizeof(Float)];
>> + };
>> + const char *t = first;
>> + char *e = buf;
>> + for (; t != last; ++t, ++e) {
>> + unsigned d1 = isdigit(*t) ?
>> static_cast<unsigned>(*t - '0')
>> + :
>> static_cast<unsigned>(*t - 'a' + 10);
>> + ++t;
>> + unsigned d0 = isdigit(*t) ?
>> static_cast<unsigned>(*t - '0')
>> + :
>> static_cast<unsigned>(*t - 'a' + 10);
>> + *e = static_cast<char>((d1 << 4) + d0);
>> + }
>> +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
>> + std::reverse(buf, e);
>> +#endif
>> + char num[FloatData<Float>::max_demangled_size] = {0};
>> + int n = snprintf(num, sizeof(num),
>> FloatData<Float>::spec, value);
>> + s += StringView(num, num + n);
>> + }
>> + }
>> +};
>> +
>> template <std::size_t N>
>> class arena
>> {
>> @@ -148,168 +1511,118 @@ operator!=(const short_alloc<T,
>> N>& x, c
>> return !(x == y);
>> }
>>
>> -template <class T>
>> -class malloc_alloc
>> -{
>> -public:
>> - typedef T value_type;
>> - typedef T& reference;
>> - typedef const T& const_reference;
>> - typedef T* pointer;
>> - typedef const T* const_pointer;
>> - typedef std::size_t size_type;
>> - typedef std::ptrdiff_t difference_type;
>> -
>> - malloc_alloc() = default;
>> - template <class U> malloc_alloc(const
>> malloc_alloc<U>&) noexcept {}
>> -
>> - T* allocate(std::size_t n)
>> - {
>> - return static_cast<T*>(std::malloc(n*sizeof(T)));
>> - }
>> - void deallocate(T* p, std::size_t) noexcept
>> - {
>> - std::free(p);
>> - }
>> -
>> - template <class U> struct rebind { using other =
>> malloc_alloc<U>; };
>> - template <class U, class... Args>
>> - void construct(U* p, Args&&... args)
>> - {
>> - ::new ((void*)p) U(std::forward<Args>(args)...);
>> - }
>> - void destroy(T* p)
>> - {
>> - p->~T();
>> - }
>> -};
>> -
>> -template <class T, class U>
>> -inline
>> -bool
>> -operator==(const malloc_alloc<T>&, const
>> malloc_alloc<U>&) noexcept
>> -{
>> - return true;
>> -}
>> -
>> -template <class T, class U>
>> -inline
>> -bool
>> -operator!=(const malloc_alloc<T>& x, const
>> malloc_alloc<U>& 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>>;
>>
>> -template <class StrT>
>> -struct string_pair
>> -{
>> - StrT first;
>> - StrT second;
>> +class BumpPointerAllocator {
>> + struct BlockMeta {
>> + BlockMeta* Next;
>> + size_t Current;
>> + };
>> +
>> + static constexpr size_t AllocSize = 4096;
>> + static constexpr size_t UsableAllocSize = AllocSize -
>> sizeof(BlockMeta);
>> +
>> + alignas(16) char InitialBuffer[AllocSize];
>> + BlockMeta* BlockList = nullptr;
>> +
>> + void grow() {
>> + char* NewMeta = new char[AllocSize];
>> + BlockList = new (NewMeta) BlockMeta{BlockList, 0};
>> + }
>> +
>> + void* allocateMassive(size_t NBytes) {
>> + NBytes += sizeof(BlockMeta);
>> + BlockMeta* NewMeta =
>> reinterpret_cast<BlockMeta*>(new char[NBytes]);
>> + BlockList->Next = new (NewMeta)
>> BlockMeta{BlockList->Next, 0};
>> + return static_cast<void*>(NewMeta + 1);
>> + }
>>
>> - string_pair() = default;
>> - string_pair(StrT f) : first(std::move(f)) {}
>> - string_pair(StrT f, StrT s)
>> - : first(std::move(f)), second(std::move(s)) {}
>> - template <size_t N>
>> - string_pair(const char (&s)[N]) : first(s, N-1) {}
>> +public:
>> + BumpPointerAllocator()
>> + : BlockList(new (InitialBuffer) BlockMeta{nullptr,
>> 0}) {}
>>
>> - 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);}
>> + void* allocate(size_t N) {
>> + N = (N + 15u) & ~15u;
>> + if (N + BlockList->Current >= UsableAllocSize) {
>> + if (N > UsableAllocSize)
>> + return allocateMassive(N);
>> + grow();
>> + }
>> + BlockList->Current += N;
>> + return
>> static_cast<void*>(reinterpret_cast<char*>(BlockList + 1) +
>> + BlockList->Current - N);
>> + }
>> +
>> + ~BumpPointerAllocator() {
>> + while (BlockList) {
>> + BlockMeta* Tmp = BlockList;
>> + BlockList = BlockList->Next;
>> + if (reinterpret_cast<char*>(Tmp) != InitialBuffer)
>> + delete[] reinterpret_cast<char*>(Tmp);
>> + }
>> + }
>> };
>>
>> struct Db
>> {
>> - typedef std::basic_string<char, std::char_traits<char>,
>> - malloc_alloc<char>> String;
>> - typedef Vector<string_pair<String>> sub_type;
>> + typedef Vector<Node*> sub_type;
>> typedef Vector<sub_type> template_param_type;
>> sub_type names;
>> template_param_type subs;
>> Vector<template_param_type> template_param;
>> - unsigned cv = 0;
>> - unsigned ref = 0;
>> + Qualifiers cv = QualNone;
>> + FunctionRefQual ref = FrefQualNone;
>> unsigned encoding_depth = 0;
>> bool parsed_ctor_dtor_cv = false;
>> bool tag_templates = true;
>> bool fix_forward_references = false;
>> bool try_to_parse_template_args = true;
>>
>> + BumpPointerAllocator ASTAllocator;
>> +
>> template <size_t N>
>> Db(arena<N>& ar) :
>> names(ar),
>> subs(0, names, ar),
>> template_param(0, subs, ar)
>> {}
>> -};
>> -
>>
>> -const char* parse_type(const char* first, const char*
>> last, Db& db);
>> -const char* parse_encoding(const char* first, const
>> char* last, Db& db);
>> -const char* parse_name(const char* first, const char*
>> last, Db& db,
>> - bool* ends_with_template_args = 0);
>> -const char* parse_expression(const char* first, const
>> char* last, Db& db);
>> -const char* parse_template_args(const char* first, const
>> char* last, Db& db);
>> -const char* parse_operator_name(const char* first, const
>> char* last, Db& db);
>> -const char* parse_unqualified_name(const char* first,
>> const char* last, Db& db);
>> -const char* parse_decltype(const char* first, const
>> char* last, Db& db);
>> + template <class T, class... Args> T* make(Args&&
>> ...args)
>> + {
>> + return new (ASTAllocator.allocate(sizeof(T)))
>> + T(std::forward<Args>(args)...);
>> + }
>>
>> -template <class C>
>> -void
>> -print_stack(const C& db)
>> -{
>> - fprintf(stderr, "---------\n");
>> - fprintf(stderr, "names:\n");
>> - for (auto& s : db.names)
>> - fprintf(stderr, "{%s#%s}\n", s.first.c_str(),
>> s.second.c_str());
>> - int i = -1;
>> - fprintf(stderr, "subs:\n");
>> - for (auto& v : db.subs)
>> + template <class It> NodeArray makeNodeArray(It
>> begin, It end)
>> {
>> - if (i >= 0)
>> - fprintf(stderr, "S%i_ = {", i);
>> - else
>> - fprintf(stderr, "S_ = {");
>> - for (auto& s : v)
>> - fprintf(stderr, "{%s#%s}", s.first.c_str(),
>> s.second.c_str());
>> - fprintf(stderr, "}\n");
>> - ++i;
>> - }
>> - fprintf(stderr, "template_param:\n");
>> - for (auto& t : db.template_param)
>> - {
>> - fprintf(stderr, "--\n");
>> - i = -1;
>> - for (auto& v : t)
>> - {
>> - if (i >= 0)
>> - fprintf(stderr, "T%i_ = {", i);
>> - else
>> - fprintf(stderr, "T_ = {");
>> - for (auto& s : v)
>> - fprintf(stderr, "{%s#%s}",
>> s.first.c_str(), s.second.c_str());
>> - fprintf(stderr, "}\n");
>> - ++i;
>> - }
>> + size_t sz = static_cast<size_t>(end - begin);
>> + void* mem = ASTAllocator.allocate(sizeof(Node*)
>> * sz);
>> + Node** data = new (mem) Node*[sz];
>> + std::copy(begin, end, data);
>> + return NodeArray(data, sz);
>> }
>> - fprintf(stderr, "---------\n\n");
>> -}
>>
>> -template <class C>
>> -void
>> -print_state(const char* msg, const char* first, const
>> char* last, const C& db)
>> -{
>> - fprintf(stderr, "%s: ", msg);
>> - for (; first != last; ++first)
>> - fprintf(stderr, "%c", *first);
>> - fprintf(stderr, "\n");
>> - print_stack(db);
>> -}
>> + NodeArray popTrailingNodeArray(size_t FromPosition)
>> + {
>> + assert(FromPosition <= names.size());
>> + NodeArray res = makeNodeArray(
>> + names.begin() + (long)FromPosition,
>> names.end());
>> + names.erase(names.begin() + (long)FromPosition,
>> names.end());
>> + return res;
>> + }
>> +};
>> +
>> +const char* parse_type(const char* first, const char*
>> last, Db& db);
>> +const char* parse_encoding(const char* first, const
>> char* last, Db& db);
>> +const char* parse_name(const char* first, const char*
>> last, Db& db,
>> + bool* ends_with_template_args = 0);
>> +const char* parse_expression(const char* first, const
>> char* last, Db& db);
>> +const char* parse_template_args(const char* first, const
>> char* last, Db& db);
>> +const char* parse_operator_name(const char* first, const
>> char* last, Db& db);
>> +const char* parse_unqualified_name(const char* first,
>> const char* last, Db& db);
>> +const char* parse_decltype(const char* first, const
>> char* last, Db& db);
>>
>> // <number> ::= [n] <non-negative decimal integer>
>>
>> @@ -339,30 +1652,30 @@ parse_number(const char* first,
>> const ch
>> }
>>
>> template <class Float>
>> -struct float_data;
>> +struct FloatData;
>>
>> template <>
>> -struct float_data<float>
>> +struct FloatData<float>
>> {
>> static const size_t mangled_size = 8;
>> static const size_t max_demangled_size = 24;
>> static constexpr const char* spec = "%af";
>> };
>>
>> -constexpr const char* float_data<float>::spec;
>> +constexpr const char* FloatData<float>::spec;
>>
>> template <>
>> -struct float_data<double>
>> +struct FloatData<double>
>> {
>> static const size_t mangled_size = 16;
>> static const size_t max_demangled_size = 32;
>> static constexpr const char* spec = "%a";
>> };
>>
>> -constexpr const char* float_data<double>::spec;
>> +constexpr const char* FloatData<double>::spec;
>>
>> template <>
>> -struct float_data<long double>
>> +struct FloatData<long double>
>> {
>> #if defined(__mips__) && defined(__mips_n64) ||
>> defined(__aarch64__) || \
>> defined(__wasm__)
>> @@ -376,46 +1689,27 @@ struct float_data<long double>
>> static constexpr const char* spec = "%LaL";
>> };
>>
>> -constexpr const char* float_data<long double>::spec;
>> +constexpr const char* FloatData<long double>::spec;
>>
>> template <class Float>
>> const char*
>> parse_floating_number(const char* first, const char*
>> last, Db& db)
>> {
>> - const size_t N = float_data<Float>::mangled_size;
>> - if (static_cast<std::size_t>(last - first) > N)
>> + const size_t N = FloatData<Float>::mangled_size;
>> + if (static_cast<std::size_t>(last - first) <= N)
>> + return first;
>> + last = first + N;
>> + const char* t = first;
>> + for (; t != last; ++t)
>> {
>> - last = first + N;
>> - union
>> - {
>> - Float value;
>> - char buf[sizeof(Float)];
>> - };
>> - const char* t = first;
>> - char* e = buf;
>> - for (; t != last; ++t, ++e)
>> - {
>> - if (!isxdigit(*t))
>> - return first;
>> - unsigned d1 = isdigit(*t) ?
>> static_cast<unsigned>(*t - '0') :
>> - static_cast<unsigned>(*t - 'a' + 10);
>> - ++t;
>> - unsigned d0 = isdigit(*t) ?
>> static_cast<unsigned>(*t - '0') :
>> - static_cast<unsigned>(*t - 'a' + 10);
>> - *e = static_cast<char>((d1 << 4) + d0);
>> - }
>> - if (*t == 'E')
>> - {
>> -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
>> - std::reverse(buf, e);
>> -#endif
>> - char
>> num[float_data<Float>::max_demangled_size] = {0};
>> - int n = snprintf(num, sizeof(num),
>> float_data<Float>::spec, value);
>> - if (static_cast<std::size_t>(n) >= sizeof(num))
>> - return first;
>> - db.names.push_back(Db::String(num,
>> static_cast<std::size_t>(n)));
>> - first = t+1;
>> - }
>> + if (!isxdigit(*t))
>> + return first;
>> + }
>> + if (*t == 'E')
>> + {
>> + db.names.push_back(
>> + db.make<FloatExpr<Float>>(StringView(first, t)));
>> + first = t + 1;
>> }
>> return first;
>> }
>> @@ -440,11 +1734,11 @@ parse_source_name(const char*
>> first, con
>> }
>> if (static_cast<size_t>(last - t) >= n)
>> {
>> - Db::String r(t, n);
>> + StringView r(t, t + n);
>> if (r.substr(0, 10) == "_GLOBAL__N")
>> - db.names.push_back("(anonymous namespace)");
>> + db.names.push_back(db.make<NameType>("(anonymous
>> namespace)"));
>> else
>> - db.names.push_back(std::move(r));
>> + db.names.push_back(db.make<NameType>(r));
>> first = t + n;
>> }
>> }
>> @@ -473,27 +1767,32 @@ parse_substitution(const char*
>> first, co
>> switch (first[1])
>> {
>> case 'a':
>> - db.names.push_back("std::allocator");
>> + db.names.push_back(
>> + db.make<SpecialSubstitution>(
>> + SpecialSubKind::allocator));
>> first += 2;
>> break;
>> case 'b':
>> - db.names.push_back("std::basic_string");
>> + db.names.push_back(
>> +
>> db.make<SpecialSubstitution>(SpecialSubKind::basic_string));
>> first += 2;
>> break;
>> case 's':
>> - db.names.push_back("std::string");
>> + db.names.push_back(
>> + db.make<SpecialSubstitution>(
>> + SpecialSubKind::string));
>> first += 2;
>> break;
>> case 'i':
>> - db.names.push_back("std::istream");
>> +
>> db.names.push_back(db.make<SpecialSubstitution>(SpecialSubKind::istream));
>> first += 2;
>> break;
>> case 'o':
>> - db.names.push_back("std::ostream");
>> +
>> db.names.push_back(db.make<SpecialSubstitution>(SpecialSubKind::ostream));
>> first += 2;
>> break;
>> case 'd':
>> - db.names.push_back("std::iostream");
>> +
>> db.names.push_back(db.make<SpecialSubstitution>(SpecialSubKind::iostream));
>> first += 2;
>> break;
>> case '_':
>> @@ -578,87 +1877,87 @@ parse_builtin_type(const char*
>> first, co
>> switch (*first)
>> {
>> case 'v':
>> - db.names.push_back("void");
>> + db.names.push_back(db.make<NameType>("void"));
>> ++first;
>> break;
>> case 'w':
>> - db.names.push_back("wchar_t");
>> + db.names.push_back(db.make<NameType>("wchar_t"));
>> ++first;
>> break;
>> case 'b':
>> - db.names.push_back("bool");
>> + db.names.push_back(db.make<NameType>("bool"));
>> ++first;
>> break;
>> case 'c':
>> - db.names.push_back("char");
>> + db.names.push_back(db.make<NameType>("char"));
>> ++first;
>> break;
>> case 'a':
>> - db.names.push_back("signed char");
>> + db.names.push_back(db.make<NameType>("signed char"));
>> ++first;
>> break;
>> case 'h':
>> - db.names.push_back("unsigned char");
>> + db.names.push_back(db.make<NameType>("unsigned char"));
>> ++first;
>> break;
>> case 's':
>> - db.names.push_back("short");
>> + db.names.push_back(db.make<NameType>("short"));
>> ++first;
>> break;
>> case 't':
>> - db.names.push_back("unsigned short");
>> + db.names.push_back(db.make<NameType>("unsigned short"));
>> ++first;
>> break;
>> case 'i':
>> - db.names.push_back("int");
>> + db.names.push_back(db.make<NameType>("int"));
>> ++first;
>> break;
>> case 'j':
>> - db.names.push_back("unsigned int");
>> + db.names.push_back(db.make<NameType>("unsigned int"));
>> ++first;
>> break;
>> case 'l':
>> - db.names.push_back("long");
>> + db.names.push_back(db.make<NameType>("long"));
>> ++first;
>> break;
>> case 'm':
>> - db.names.push_back("unsigned long");
>> + db.names.push_back(db.make<NameType>("unsigned long"));
>> ++first;
>> break;
>> case 'x':
>> - db.names.push_back("long long");
>> + db.names.push_back(db.make<NameType>("long long"));
>> ++first;
>> break;
>> case 'y':
>> - db.names.push_back("unsigned long long");
>> + db.names.push_back(db.make<NameType>("unsigned long
>> long"));
>> ++first;
>> break;
>> case 'n':
>> - db.names.push_back("__int128");
>> + db.names.push_back(db.make<NameType>("__int128"));
>> ++first;
>> break;
>> case 'o':
>> - db.names.push_back("unsigned __int128");
>> + db.names.push_back(db.make<NameType>("unsigned __int128"));
>> ++first;
>> break;
>> case 'f':
>> - db.names.push_back("float");
>> + db.names.push_back(db.make<NameType>("float"));
>> ++first;
>> break;
>> case 'd':
>> - db.names.push_back("double");
>> + db.names.push_back(db.make<NameType>("double"));
>> ++first;
>> break;
>> case 'e':
>> - db.names.push_back("long double");
>> + db.names.push_back(db.make<NameType>("long double"));
>> ++first;
>> break;
>> case 'g':
>> - db.names.push_back("__float128");
>> + db.names.push_back(db.make<NameType>("__float128"));
>> ++first;
>> break;
>> case 'z':
>> - db.names.push_back("...");
>> + db.names.push_back(db.make<NameType>("..."));
>> ++first;
>> break;
>> case 'u':
>> @@ -674,39 +1973,39 @@ parse_builtin_type(const char*
>> first, co
>> switch (first[1])
>> {
>> case 'd':
>> - db.names.push_back("decimal64");
>> + db.names.push_back(db.make<NameType>("decimal64"));
>> first += 2;
>> break;
>> case 'e':
>> - db.names.push_back("decimal128");
>> + db.names.push_back(db.make<NameType>("decimal128"));
>> first += 2;
>> break;
>> case 'f':
>> - db.names.push_back("decimal32");
>> + db.names.push_back(db.make<NameType>("decimal32"));
>> first += 2;
>> break;
>> case 'h':
>> - db.names.push_back("decimal16");
>> + db.names.push_back(db.make<NameType>("decimal16"));
>> first += 2;
>> break;
>> case 'i':
>> - db.names.push_back("char32_t");
>> + db.names.push_back(db.make<NameType>("char32_t"));
>> first += 2;
>> break;
>> case 's':
>> - db.names.push_back("char16_t");
>> + db.names.push_back(db.make<NameType>("char16_t"));
>> first += 2;
>> break;
>> case 'a':
>> - db.names.push_back("auto");
>> + db.names.push_back(db.make<NameType>("auto"));
>> first += 2;
>> break;
>> case 'c':
>> - db.names.push_back("decltype(auto)");
>> + db.names.push_back(db.make<NameType>("decltype(auto)"));
>> first += 2;
>> break;
>> case 'n':
>> - db.names.push_back("std::nullptr_t");
>> + db.names.push_back(db.make<NameType>("std::nullptr_t"));
>> first += 2;
>> break;
>> }
>> @@ -717,27 +2016,27 @@ parse_builtin_type(const char*
>> first, co
>> return first;
>> }
>>
>> -// <CV-qualifiers> ::= [r] [V] [K]
>> +// <CV-Qualifiers> ::= [r] [V] [K]
>>
>> const char*
>> -parse_cv_qualifiers(const char* first, const char* last,
>> unsigned& cv)
>> +parse_cv_qualifiers(const char* first, const char* last,
>> Qualifiers& cv)
>> {
>> - cv = 0;
>> + cv = QualNone;
>> if (first != last)
>> {
>> if (*first == 'r')
>> {
>> - cv |= 4;
>> + addQualifiers(cv, QualRestrict);
>> ++first;
>> }
>> if (*first == 'V')
>> {
>> - cv |= 2;
>> + addQualifiers(cv, QualVolatile);
>> ++first;
>> }
>> if (*first == 'K')
>> {
>> - cv |= 1;
>> + addQualifiers(cv, QualConst);
>> ++first;
>> }
>> }
>> @@ -766,7 +2065,7 @@ parse_template_param(const char* first,
>> }
>> else
>> {
>> - db.names.push_back("T_");
>> + db.names.push_back(db.make<NameType>("T_"));
>> first += 2;
>> db.fix_forward_references = true;
>> }
>> @@ -791,7 +2090,8 @@ parse_template_param(const char* first,
>> }
>> else
>> {
>> - db.names.push_back(Db::String(first, t+1));
>> + db.names.push_back(
>> + db.make<NameType>(StringView(first, t + 1)));
>> first = t+1;
>> db.fix_forward_references = true;
>> }
>> @@ -816,11 +2116,12 @@ parse_const_cast_expr(const char*
>> first,
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto expr = db.names.back().move_full();
>> + auto from_expr = db.names.back();
>> db.names.pop_back();
>> if (db.names.empty())
>> return first;
>> - db.names.back() = "const_cast<" +
>> db.names.back().move_full() + ">(" + expr + ")";
>> + db.names.back() = db.make<CastExpr>(
>> + "const_cast", db.names.back(),
>> from_expr);
>> first = t1;
>> }
>> }
>> @@ -843,11 +2144,12 @@ parse_dynamic_cast_expr(const
>> char* firs
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto expr = db.names.back().move_full();
>> + auto from_expr = db.names.back();
>> db.names.pop_back();
>> if (db.names.empty())
>> return first;
>> - db.names.back() = "dynamic_cast<" +
>> db.names.back().move_full() + ">(" + expr + ")";
>> + db.names.back() = db.make<CastExpr>(
>> + "dynamic_cast", db.names.back(),
>> from_expr);
>> first = t1;
>> }
>> }
>> @@ -870,11 +2172,12 @@ parse_reinterpret_cast_expr(const
>> char*
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto expr = db.names.back().move_full();
>> + auto from_expr = db.names.back();
>> db.names.pop_back();
>> if (db.names.empty())
>> return first;
>> - db.names.back() = "reinterpret_cast<" +
>> db.names.back().move_full() + ">(" + expr + ")";
>> + db.names.back() = db.make<CastExpr>(
>> + "reinterpret_cast", db.names.back(),
>> from_expr);
>> first = t1;
>> }
>> }
>> @@ -897,9 +2200,10 @@ parse_static_cast_expr(const char*
>> first
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto expr = db.names.back().move_full();
>> + auto from_expr = db.names.back();
>> db.names.pop_back();
>> - db.names.back() = "static_cast<" +
>> db.names.back().move_full() + ">(" + expr + ")";
>> + db.names.back() = db.make<CastExpr>(
>> + "static_cast", db.names.back(),
>> from_expr);
>> first = t1;
>> }
>> }
>> @@ -933,7 +2237,8 @@ parse_sizeof_type_expr(const char* first
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back() = "sizeof (" +
>> db.names.back().move_full() + ")";
>> + db.names.back() = db.make<EnclosingExpr>(
>> + "sizeof (", db.names.back(), ")");
>> first = t;
>> }
>> }
>> @@ -952,7 +2257,8 @@ parse_sizeof_expr_expr(const char* first
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back() = "sizeof (" +
>> db.names.back().move_full() + ")";
>> + db.names.back() = db.make<EnclosingExpr>(
>> + "sizeof (", db.names.back(), ")");
>> first = t;
>> }
>> }
>> @@ -969,30 +2275,21 @@ parse_sizeof_param_pack_expr(const
>> char*
>> size_t k0 = db.names.size();
>> const char* t = parse_template_param(first+2,
>> last, db);
>> size_t k1 = db.names.size();
>> - if (t != first+2)
>> + if (t != first+2 && k0 <= k1)
>> {
>> - Db::String tmp("sizeof...(");
>> - size_t k = k0;
>> - if (k != k1)
>> - {
>> - tmp += db.names[k].move_full();
>> - for (++k; k != k1; ++k)
>> - tmp += ", " + db.names[k].move_full();
>> - }
>> - tmp += ")";
>> - for (; k1 != k0; --k1)
>> - db.names.pop_back();
>> - db.names.push_back(std::move(tmp));
>> + Node* sizeof_expr =
>> db.make<SizeofParamPackExpr>(
>> + db.popTrailingNodeArray(k0));
>> + db.names.push_back(sizeof_expr);
>> first = t;
>> }
>> }
>> return first;
>> }
>>
>> -// <function-param> ::= fp <top-level CV-qualifiers> _
>> # L == 0, first parameter
>> -// ::= fp <top-level CV-qualifiers>
>> <parameter-2 non-negative number> _ # L == 0, second
>> and later parameters
>> -// ::= fL <L-1 non-negative number> p
>> <top-level CV-qualifiers> _ # L > 0, first parameter
>> -// ::= fL <L-1 non-negative number> p
>> <top-level CV-qualifiers> <parameter-2 non-negative
>> number> _ # L > 0, second and later parameters
>> +// <function-param> ::= fp <top-level CV-Qualifiers> _
>> # L == 0, first parameter
>> +// ::= fp <top-level CV-Qualifiers>
>> <parameter-2 non-negative number> _ # L == 0, second
>> and later parameters
>> +// ::= fL <L-1 non-negative number> p
>> <top-level CV-Qualifiers> _ # L > 0, first parameter
>> +// ::= fL <L-1 non-negative number> p
>> <top-level CV-Qualifiers> <parameter-2 non-negative
>> number> _ # L > 0, second and later parameters
>>
>> const char*
>> parse_function_param(const char* first, const char*
>> last, Db& db)
>> @@ -1001,18 +2298,19 @@ parse_function_param(const char*
>> first,
>> {
>> if (first[1] == 'p')
>> {
>> - unsigned cv;
>> + Qualifiers cv;
>> const char* t = parse_cv_qualifiers(first+2,
>> last, cv);
>> const char* t1 = parse_number(t, last);
>> if (t1 != last && *t1 == '_')
>> {
>> - db.names.push_back("fp" + Db::String(t,
>> t1));
>> + db.names.push_back(
>> + db.make<FunctionParam>(StringView(t, t1)));
>> first = t1+1;
>> }
>> }
>> else if (first[1] == 'L')
>> {
>> - unsigned cv;
>> + Qualifiers cv;
>> const char* t0 = parse_number(first+2, last);
>> if (t0 != last && *t0 == 'p')
>> {
>> @@ -1021,7 +2319,8 @@ parse_function_param(const char* first,
>> const char* t1 = parse_number(t, last);
>> if (t1 != last && *t1 == '_')
>> {
>> - db.names.push_back("fp" +
>> Db::String(t, t1));
>> + db.names.push_back(
>> + db.make<FunctionParam>(StringView(t, t1)));
>> first = t1+1;
>> }
>> }
>> @@ -1042,7 +2341,8 @@
>> parse_sizeof_function_param_pack_expr(co
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back() = "sizeof...(" +
>> db.names.back().move_full() + ")";
>> + db.names.back() = db.make<EnclosingExpr>(
>> + "sizeof...(", db.names.back(), ")");
>> first = t;
>> }
>> }
>> @@ -1066,7 +2366,8 @@ parse_typeid_expr(const char*
>> first, con
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back() = "typeid(" +
>> db.names.back().move_full() + ")";
>> + db.names.back() = db.make<EnclosingExpr>(
>> + "typeid(", db.names.back(), ")");
>> first = t;
>> }
>> }
>> @@ -1085,7 +2386,7 @@ parse_throw_expr(const char* first,
>> cons
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back() = "throw " +
>> db.names.back().move_full();
>> + db.names.back() =
>> db.make<ThrowExpr>(db.names.ba <http://db.names.ba>ck());
>> first = t;
>> }
>> }
>> @@ -1107,9 +2408,10 @@ parse_dot_star_expr(const char*
>> first, c
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto expr = db.names.back().move_full();
>> + auto rhs_expr = db.names.back();
>> db.names.pop_back();
>> - db.names.back().first += ".*" + expr;
>> + db.names.back() = db.make<MemberExpr>(
>> + db.names.back(), ".*", rhs_expr);
>> first = t1;
>> }
>> }
>> @@ -1132,9 +2434,10 @@ parse_simple_id(const char* first,
>> const
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto args = db.names.back().move_full();
>> + auto args = db.names.back();
>> db.names.pop_back();
>> - db.names.back().first += std::move(args);
>> + db.names.back() =
>> + db.make<NameWithTemplateArgs>(db.names.back(), args);
>> }
>> first = t1;
>> }
>> @@ -1196,7 +2499,8 @@ parse_unresolved_type(const char*
>> first,
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "std::");
>> + db.names.back() =
>> + db.make<StdQualifiedName>(db.names.back());
>> db.subs.push_back(Db::sub_type(1, db.names.back(),
>> db.names.get_allocator()));
>> first = t;
>> }
>> @@ -1223,7 +2527,7 @@ parse_destructor_name(const char*
>> first,
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "~");
>> + db.names.back() =
>> db.make<DtorName>(db.names.back());
>> first = t;
>> }
>> }
>> @@ -1255,9 +2559,11 @@ parse_base_unresolved_name(const
>> char* f
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto args =
>> db.names.back().move_full();
>> + auto args = db.names.back();
>> db.names.pop_back();
>> - db.names.back().first += std::move(args);
>> + db.names.back() =
>> + db.make<NameWithTemplateArgs>(
>> + db.names.back(), args);
>> }
>> }
>> }
>> @@ -1281,9 +2587,11 @@ parse_base_unresolved_name(const
>> char* f
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto args =
>> db.names.back().move_full();
>> + auto args = db.names.back();
>> db.names.pop_back();
>> - db.names.back().first += std::move(args);
>> + db.names.back() =
>> + db.make<NameWithTemplateArgs>(
>> + db.names.back(), args);
>> }
>> }
>> }
>> @@ -1331,7 +2639,8 @@ parse_unresolved_name(const char*
>> first,
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "::");
>> + db.names.back() =
>> + db.make<GlobalQualifiedName>(db.names.back());
>> }
>> first = t2;
>> }
>> @@ -1349,9 +2658,10 @@ parse_unresolved_name(const char*
>> first,
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto args = db.names.back().move_full();
>> + auto args = db.names.back();
>> db.names.pop_back();
>> - db.names.back().first +=
>> std::move(args);
>> + db.names.back() =
>> db.make<NameWithTemplateArgs>(
>> + db.names.back(), args);
>> t = t1;
>> if (t == last)
>> {
>> @@ -1364,9 +2674,10 @@ parse_unresolved_name(const char*
>> first,
>> t1 =
>> parse_unresolved_qualifier_level(t, last, db);
>> if (t1 == t || t1 == last ||
>> db.names.size() < 2)
>> return first;
>> - auto s = db.names.back().move_full();
>> + auto s = db.names.back();
>> db.names.pop_back();
>> - db.names.back().first += "::" +
>> std::move(s);
>> + db.names.back() =
>> + db.make<QualifiedName>(db.name
>> <http://db.name>s.back(), s);
>> t = t1;
>> }
>> ++t;
>> @@ -1379,9 +2690,10 @@ parse_unresolved_name(const char*
>> first,
>> }
>> if (db.names.size() < 2)
>> return first;
>> - auto s = db.names.back().move_full();
>> + auto s = db.names.back();
>> db.names.pop_back();
>> - db.names.back().first += "::" +
>> std::move(s);
>> + db.names.back() =
>> + db.make<QualifiedName>(db.name
>> <http://db.name>s.back(), s);
>> first = t1;
>> }
>> else
>> @@ -1396,9 +2708,11 @@ parse_unresolved_name(const char*
>> first,
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto args =
>> db.names.back().move_full();
>> + auto args = db.names.back();
>> db.names.pop_back();
>> - db.names.back().first += std::move(args);
>> + db.names.back() =
>> + db.make<NameWithTemplateArgs>(
>> + db.names.back(), args);
>> t = t1;
>> }
>> t1 = parse_base_unresolved_name(t,
>> last, db);
>> @@ -1410,9 +2724,10 @@ parse_unresolved_name(const char*
>> first,
>> }
>> if (db.names.size() < 2)
>> return first;
>> - auto s = db.names.back().move_full();
>> + auto s = db.names.back();
>> db.names.pop_back();
>> - db.names.back().first += "::" +
>> std::move(s);
>> + db.names.back() =
>> + db.make<QualifiedName>(db.name
>> <http://db.name>s.back(), s);
>> first = t1;
>> }
>> else
>> @@ -1425,16 +2740,19 @@ parse_unresolved_name(const char*
>> first,
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "::");
>> + db.names.back() =
>> + db.make<GlobalQualifiedName>(
>> + db.names.back());
>> }
>> while (*t != 'E')
>> {
>> t1 =
>> parse_unresolved_qualifier_level(t, last, db);
>> if (t1 == t || t1 == last ||
>> db.names.size() < 2)
>> return first;
>> - auto s =
>> db.names.back().move_full();
>> + auto s = db.names.back();
>> db.names.pop_back();
>> - db.names.back().first += "::" + std::move(s);
>> + db.names.back() =
>> db.make<QualifiedName>(
>> + db.names.back(), s);
>> t = t1;
>> }
>> ++t;
>> @@ -1447,9 +2765,10 @@ parse_unresolved_name(const char*
>> first,
>> }
>> if (db.names.size() < 2)
>> return first;
>> - auto s = db.names.back().move_full();
>> + auto s = db.names.back();
>> db.names.pop_back();
>> - db.names.back().first += "::" +
>> std::move(s);
>> + db.names.back() =
>> + db.make<QualifiedName>(db.name
>> <http://db.name>s.back(), s);
>> first = t1;
>> }
>> }
>> @@ -1473,11 +2792,11 @@ parse_dot_expr(const char* first,
>> const
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto name = db.names.back().move_full();
>> + auto name = db.names.back();
>> db.names.pop_back();
>> if (db.names.empty())
>> return first;
>> - db.names.back().first += "." + name;
>> + db.names.back() =
>> db.make<MemberExpr>(db.names.back(), ".", name);
>> first = t1;
>> }
>> }
>> @@ -1493,44 +2812,25 @@ parse_call_expr(const char*
>> first, const
>> if (last - first >= 4 && first[0] == 'c' && first[1]
>> == 'l')
>> {
>> const char* t = parse_expression(first+2, last, db);
>> - if (t != first+2)
>> + if (t == last || t == first + 2 || db.names.empty())
>> + return first;
>> + Node* callee = db.names.back();
>> + db.names.pop_back();
>> + size_t args_begin = db.names.size();
>> + while (*t != 'E')
>> {
>> - if (t == last)
>> - return first;
>> - if (db.names.empty())
>> - return first;
>> - db.names.back().first += db.names.back().second;
>> - db.names.back().second = Db::String();
>> - db.names.back().first.append("(");
>> - bool first_expr = true;
>> - while (*t != 'E')
>> - {
>> - const char* t1 = parse_expression(t,
>> last, db);
>> - if (t1 == t || t1 == last)
>> - return first;
>> - if (db.names.empty())
>> - return first;
>> - auto tmp = db.names.back().move_full();
>> - db.names.pop_back();
>> - if (!tmp.empty())
>> - {
>> - if (db.names.empty())
>> - return first;
>> - if (!first_expr)
>> - {
>> - db.names.back().first.append(", ");
>> - first_expr = false;
>> - }
>> - db.names.back().first.append(tmp);
>> - }
>> - t = t1;
>> - }
>> - ++t;
>> - if (db.names.empty())
>> + const char* t1 = parse_expression(t, last, db);
>> + if (t1 == last || t1 == t)
>> return first;
>> - db.names.back().first.append(")");
>> - first = t;
>> + t = t1;
>> }
>> + if (db.names.size() < args_begin)
>> + return first;
>> + ++t;
>> + CallExpr* the_call = db.make<CallExpr>(
>> + callee, db.popTrailingNodeArray(args_begin));
>> + db.names.push_back(the_call);
>> + first = t;
>> }
>> return first;
>> }
>> @@ -1559,31 +2859,18 @@ parse_new_expr(const char* first,
>> const
>> t += 2;
>> if (t == last)
>> return first;
>> - bool has_expr_list = false;
>> - bool first_expr = true;
>> + size_t first_expr_in_list = db.names.size();
>> + NodeArray ExprList, init_list;
>> while (*t != '_')
>> {
>> const char* t1 = parse_expression(t,
>> last, db);
>> if (t1 == t || t1 == last)
>> return first;
>> - has_expr_list = true;
>> - if (!first_expr)
>> - {
>> - if (db.names.empty())
>> - return first;
>> - auto tmp = db.names.back().move_full();
>> - db.names.pop_back();
>> - if (!tmp.empty())
>> - {
>> - if (db.names.empty())
>> - return first;
>> - db.names.back().first.append(", ");
>> - db.names.back().first.append(tmp);
>> - first_expr = false;
>> - }
>> - }
>> t = t1;
>> }
>> + if (first_expr_in_list < db.names.size())
>> + return first;
>> + ExprList =
>> db.popTrailingNodeArray(first_expr_in_list);
>> ++t;
>> const char* t1 = parse_type(t, last, db);
>> if (t1 == t || t1 == last)
>> @@ -1594,65 +2881,25 @@ parse_new_expr(const char* first,
>> const
>> {
>> t += 2;
>> has_init = true;
>> - first_expr = true;
>> + size_t init_list_begin = db.names.size();
>> while (*t != 'E')
>> {
>> t1 = parse_expression(t, last, db);
>> if (t1 == t || t1 == last)
>> return first;
>> - if (!first_expr)
>> - {
>> - if (db.names.empty())
>> - return first;
>> - auto tmp =
>> db.names.back().move_full();
>> - db.names.pop_back();
>> - if (!tmp.empty())
>> - {
>> - if (db.names.empty())
>> - return first;
>> - db.names.back().first.append(", ");
>> - db.names.back().first.append(tmp);
>> - first_expr = false;
>> - }
>> - }
>> t = t1;
>> }
>> - }
>> - if (*t != 'E')
>> - return first;
>> - Db::String init_list;
>> - if (has_init)
>> - {
>> - if (db.names.empty())
>> + if (init_list_begin < db.names.size())
>> return first;
>> - init_list = db.names.back().move_full();
>> - db.names.pop_back();
>> + init_list =
>> db.popTrailingNodeArray(init_list_begin);
>> }
>> - if (db.names.empty())
>> + if (*t != 'E')
>> return first;
>> - auto type = db.names.back().move_full();
>> + auto type = db.names.back();
>> db.names.pop_back();
>> - Db::String expr_list;
>> - if (has_expr_list)
>> - {
>> - if (db.names.empty())
>> - return first;
>> - expr_list = db.names.back().move_full();
>> - db.names.pop_back();
>> - }
>> - Db::String r;
>> - if (parsed_gs)
>> - r = "::";
>> - if (is_array)
>> - r += "[] ";
>> - else
>> - r += " ";
>> - if (has_expr_list)
>> - r += "(" + expr_list + ") ";
>> - r += type;
>> - if (has_init)
>> - r += " (" + init_list + ")";
>> - db.names.push_back(std::move(r));
>> + db.names.push_back(
>> + db.make<NewExpr>(ExprList, type, init_list,
>> + parsed_gs, is_array));
>> first = t+1;
>> }
>> }
>> @@ -1669,10 +2916,12 @@ parse_conversion_expr(const char*
>> first,
>> {
>> bool try_to_parse_template_args =
>> db.try_to_parse_template_args;
>> db.try_to_parse_template_args = false;
>> + size_t type_begin = db.names.size();
>> const char* t = parse_type(first+2, last, db);
>> db.try_to_parse_template_args =
>> try_to_parse_template_args;
>> if (t != first+2 && t != last)
>> {
>> + size_t ExprList_begin = db.names.size();
>> if (*t != '_')
>> {
>> const char* t1 = parse_expression(t,
>> last, db);
>> @@ -1685,41 +2934,30 @@ parse_conversion_expr(const char*
>> first,
>> ++t;
>> if (t == last)
>> return first;
>> - if (*t == 'E')
>> - db.names.emplace_back();
>> - else
>> + if (*t != 'E')
>> {
>> - bool first_expr = true;
>> while (*t != 'E')
>> {
>> const char* t1 =
>> parse_expression(t, last, db);
>> if (t1 == t || t1 == last)
>> return first;
>> - if (!first_expr)
>> - {
>> - if (db.names.empty())
>> - return first;
>> - auto tmp =
>> db.names.back().move_full();
>> - db.names.pop_back();
>> - if (!tmp.empty())
>> - {
>> - if (db.names.empty())
>> - return first;
>> - db.names.back().first.append(", ");
>> - db.names.back().first.append(tmp);
>> - first_expr = false;
>> - }
>> - }
>> t = t1;
>> }
>> }
>> ++t;
>> }
>> - if (db.names.size() < 2)
>> + if (db.names.size() < ExprList_begin)
>> return first;
>> - auto tmp = db.names.back().move_full();
>> - db.names.pop_back();
>> - db.names.back() = "(" +
>> db.names.back().move_full() + ")(" + tmp + ")";
>> + NodeArray expressions = db.makeNodeArray(
>> + db.names.begin() + (long)ExprList_begin,
>> db.names.end());
>> + NodeArray types = db.makeNodeArray(
>> + db.names.begin() + (long)type_begin,
>> + db.names.begin() + (long)ExprList_begin);
>> + auto* conv_expr = db.make<ConversionExpr>(
>> + types, expressions);
>> + db.names.erase(
>> + db.names.begin() + (long)type_begin,
>> db.names.end());
>> + db.names.push_back(conv_expr);
>> first = t;
>> }
>> }
>> @@ -1741,10 +2979,10 @@ parse_arrow_expr(const char*
>> first, cons
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto tmp = db.names.back().move_full();
>> + auto tmp = db.names.back();
>> db.names.pop_back();
>> - db.names.back().first += "->";
>> - db.names.back().first += tmp;
>> + db.names.back() = db.make<MemberExpr>(
>> + db.names.back(), "->", tmp);
>> first = t1;
>> }
>> }
>> @@ -1772,11 +3010,13 @@ parse_function_type(const char*
>> first, c
>> return first;
>> }
>> const char* t1 = parse_type(t, last, db);
>> - if (t1 != t)
>> + if (t1 != t && !db.names.empty())
>> {
>> + Node* ret_type = db.names.back();
>> + db.names.pop_back();
>> + size_t params_begin = db.names.size();
>> t = t1;
>> - Db::String sig("(");
>> - int ref_qual = 0;
>> + FunctionRefQual RefQuals = FrefQualNone;
>> while (true)
>> {
>> if (t == last)
>> @@ -1797,45 +3037,30 @@ parse_function_type(const char*
>> first, c
>> }
>> if (*t == 'R' && t+1 != last && t[1]
>> == 'E')
>> {
>> - ref_qual = 1;
>> + RefQuals = FrefQualLValue;
>> ++t;
>> continue;
>> }
>> if (*t == 'O' && t+1 != last && t[1]
>> == 'E')
>> {
>> - ref_qual = 2;
>> + RefQuals = FrefQualRValue;
>> ++t;
>> continue;
>> }
>> size_t k0 = db.names.size();
>> t1 = parse_type(t, last, db);
>> size_t k1 = db.names.size();
>> - if (t1 == t || t1 == last)
>> + if (t1 == t || t1 == last || k1 < k0)
>> return first;
>> - for (size_t k = k0; k < k1; ++k)
>> - {
>> - if (sig.size() > 1)
>> - sig += ", ";
>> - sig += db.names[k].move_full();
>> - }
>> - for (size_t k = k0; k < k1; ++k)
>> - db.names.pop_back();
>> t = t1;
>> }
>> - sig += ")";
>> - switch (ref_qual)
>> - {
>> - case 1:
>> - sig += " &";
>> - break;
>> - case 2:
>> - sig += " &&";
>> - break;
>> - }
>> if (db.names.empty())
>> return first;
>> - db.names.back().first += " ";
>> - db.names.back().second.insert(0, sig);
>> + Node* fty = db.make<FunctionType>(
>> + ret_type,
>> db.popTrailingNodeArray(params_begin));
>> + if (RefQuals)
>> + fty =
>> db.make<FunctionRefQualType>(fty, RefQuals);
>> + db.names.push_back(fty);
>> first = t;
>> }
>> }
>> @@ -1860,17 +3085,9 @@ parse_pointer_to_member_type(const
>> char*
>> return first;
>> auto func = std::move(db.names.back());
>> db.names.pop_back();
>> - auto class_type =
>> std::move(db.names.back());
>> - if (!func.second.empty() &&
>> func.second.front() == '(')
>> - {
>> - db.names.back().first =
>> std::move(func.first) + "(" + class_type.move_full() + "::*";
>> - db.names.back().second = ")" +
>> std::move(func.second);
>> - }
>> - else
>> - {
>> - db.names.back().first =
>> std::move(func.first) + " " + class_type.move_full() + "::*";
>> - db.names.back().second =
>> std::move(func.second);
>> - }
>> + auto ClassType = std::move(db.names.back());
>> + db.names.back() =
>> + db.make<PointerToMemberType>(ClassType, func);
>> first = t2;
>> }
>> }
>> @@ -1893,9 +3110,7 @@ parse_array_type(const char* first,
>> cons
>> {
>> if (db.names.empty())
>> return first;
>> - if (db.names.back().second.substr(0, 2)
>> == " [")
>> - db.names.back().second.erase(0, 1);
>> - db.names.back().second.insert(0, " []");
>> + db.names.back() =
>> db.make<ArrayType>(db.names.ba <http://db.names.ba>ck());
>> first = t;
>> }
>> }
>> @@ -1909,9 +3124,9 @@ parse_array_type(const char* first,
>> cons
>> {
>> if (db.names.empty())
>> return first;
>> - if (db.names.back().second.substr(0,
>> 2) == " [")
>> - db.names.back().second.erase(0, 1);
>> - db.names.back().second.insert(0, " [" +
>> Db::String(first+1, t) + "]");
>> + db.names.back() =
>> + db.make<ArrayType>(db.names.ba <http://db.names.ba>ck(),
>> + StringView(first + 1, t));
>> first = t2;
>> }
>> }
>> @@ -1926,13 +3141,11 @@ parse_array_type(const char*
>> first, cons
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto type = std::move(db.names.back());
>> + auto base_type =
>> std::move(db.names.back());
>> db.names.pop_back();
>> - auto expr = std::move(db.names.back());
>> - db.names.back().first =
>> std::move(type.first);
>> - if (type.second.substr(0, 2) == " [")
>> - type.second.erase(0, 1);
>> - db.names.back().second = " [" +
>> expr.move_full() + "]" + std::move(type.second);
>> + auto dimension_expr =
>> std::move(db.names.back());
>> + db.names.back() =
>> + db.make<ArrayType>(base_type, dimension_expr);
>> first = t2;
>> }
>> }
>> @@ -1959,7 +3172,8 @@ parse_decltype(const char* first, const
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back() = "decltype(" +
>> db.names.back().move_full() + ")";
>> + db.names.back() =
>> db.make<EnclosingExpr>(
>> + "decltype(", db.names.back(), ")");
>> first = t+1;
>> }
>> }
>> @@ -1997,21 +3211,24 @@ parse_vector_type(const char*
>> first, con
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first += " vector[" + Db::String(num,
>> sz) + "]";
>> + db.names.back() =
>> + db.make<VectorType>(db.names.back(),
>> + StringView(num, num + sz));
>> first = t1;
>> }
>> }
>> else
>> {
>> ++t;
>> - db.names.push_back("pixel vector[" + Db::String(num,
>> sz) + "]");
>> + db.names.push_back(
>> + db.make<VectorType>(StringView(num, num + sz)));
>> first = t;
>> }
>> }
>> }
>> else
>> {
>> - Db::String num;
>> + Node* num = nullptr;
>> const char* t1 = first+2;
>> if (*t1 != '_')
>> {
>> @@ -2020,7 +3237,7 @@ parse_vector_type(const char*
>> first, con
>> {
>> if (db.names.empty())
>> return first;
>> - num = db.names.back().move_full();
>> + num = db.names.back();
>> db.names.pop_back();
>> t1 = t;
>> }
>> @@ -2032,9 +3249,15 @@ parse_vector_type(const char*
>> first, con
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first += " vector["
>> + num + "]";
>> + if (num)
>> + db.names.back() =
>> + db.make<VectorType>(db.names.back(), num);
>> + else
>> + db.names.back() =
>> + db.make<VectorType>(db.names.back(), StringView());
>> first = t;
>> - }
>> + } else if (num)
>> + db.names.push_back(num);
>> }
>> }
>> }
>> @@ -2050,7 +3273,7 @@ parse_vector_type(const char*
>> first, con
>> // ::= <template-template-param> <template-args>
>> // ::= <decltype>
>> // ::= <substitution>
>> -// ::= <CV-qualifiers> <type>
>> +// ::= <CV-Qualifiers> <type>
>> // ::= P <type> # pointer-to
>> // ::= R <type> # reference-to
>> // ::= O <type> # rvalue reference-to (C++0x)
>> @@ -2075,7 +3298,7 @@ parse_type(const char* first, const
>> char
>> case 'V':
>> case 'K':
>> {
>> - unsigned cv = 0;
>> + Qualifiers cv = QualNone;
>> const char* t =
>> parse_cv_qualifiers(first, last, cv);
>> if (t != first)
>> {
>> @@ -2090,35 +3313,13 @@ parse_type(const char* first,
>> const char
>> db.subs.emplace_back(db.names.get_allocator());
>> for (size_t k = k0; k < k1; ++k)
>> {
>> - if (is_function)
>> - {
>> - size_t p =
>> db.names[k].second.size();
>> - if (db.names[k].second[p
>> - 2] == '&' &&
>> - db.names[k].second[p - 1] == '&')
>> - p -= 2;
>> - else if
>> (db.names[k].second.back() == '&')
>> - p -= 1;
>> - if (cv & 1)
>> - {
>> - db.names[k].second.insert(p, " const");
>> - p += 6;
>> - }
>> - if (cv & 2)
>> - {
>> - db.names[k].second.insert(p, " volatile");
>> - p += 9;
>> - }
>> - if (cv & 4)
>> - db.names[k].second.insert(p, " restrict");
>> - }
>> - else
>> - {
>> - if (cv & 1)
>> - db.names[k].first.append(" const");
>> - if (cv & 2)
>> - db.names[k].first.append(" volatile");
>> - if (cv & 4)
>> - db.names[k].first.append(" restrict");
>> + if (cv) {
>> + if (is_function)
>> + db.names[k] = db.make<FunctionQualType>(
>> + db.names[k], cv);
>> + else
>> + db.names[k] =
>> + db.make<QualType>(db.names[k], cv);
>> }
>> db.subs.back().push_back(db.names[k]);
>> }
>> @@ -2154,7 +3355,8 @@ parse_type(const char* first, const
>> char
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.append(" complex");
>> + 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()));
>> }
>> @@ -2175,7 +3377,8 @@ parse_type(const char* first, const
>> char
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.append(" imaginary");
>> + 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()));
>> }
>> @@ -2200,18 +3403,8 @@ parse_type(const char* first,
>> const char
>> db.subs.emplace_back(db.names.get_allocator());
>> for (size_t k = k0; k < k1; ++k)
>> {
>> - if
>> (db.names[k].second.substr(0, 2) == " [")
>> - {
>> - db.names[k].first += " (";
>> - db.names[k].second.insert(0, ")");
>> - }
>> - else if
>> (!db.names[k].second.empty() &&
>> - db.names[k].second.front() == '(')
>> - {
>> - db.names[k].first += "(";
>> - db.names[k].second.insert(0, ")");
>> - }
>> - db.names[k].first.append("&&");
>> + db.names[k] =
>> + db.make<RValueReferenceType>(db.names[k]);
>> db.subs.back().push_back(db.names[k]);
>> }
>> first = t;
>> @@ -2228,25 +3421,7 @@ parse_type(const char* first,
>> const char
>> db.subs.emplace_back(db.names.get_allocator());
>> for (size_t k = k0; k < k1; ++k)
>> {
>> - if
>> (db.names[k].second.substr(0, 2) == " [")
>> - {
>> - db.names[k].first += " (";
>> - db.names[k].second.insert(0, ")");
>> - }
>> - else if
>> (!db.names[k].second.empty() &&
>> - db.names[k].second.front() == '(')
>> - {
>> - db.names[k].first += "(";
>> - db.names[k].second.insert(0, ")");
>> - }
>> - if (first[1] != 'U' ||
>> db.names[k].first.substr(0, 12) != "objc_object<")
>> - {
>> - db.names[k].first.append("*");
>> - }
>> - else
>> - {
>> - db.names[k].first.replace(0, 11, "id");
>> - }
>> + db.names[k] =
>> db.make<PointerType>(db.names[k]);
>> db.subs.back().push_back(db.names[k]);
>> }
>> first = t;
>> @@ -2263,18 +3438,8 @@ parse_type(const char* first,
>> const char
>> db.subs.emplace_back(db.names.get_allocator());
>> for (size_t k = k0; k < k1; ++k)
>> {
>> - if
>> (db.names[k].second.substr(0, 2) == " [")
>> - {
>> - db.names[k].first += " (";
>> - db.names[k].second.insert(0, ")");
>> - }
>> - else if
>> (!db.names[k].second.empty() &&
>> - db.names[k].second.front() == '(')
>> - {
>> - db.names[k].first += "(";
>> - db.names[k].second.insert(0, ")");
>> - }
>> - db.names[k].first.append("&");
>> + db.names[k] =
>> + db.make<LValueReferenceType>(db.names[k]);
>> db.subs.back().push_back(db.names[k]);
>> }
>> first = t;
>> @@ -2296,10 +3461,14 @@ parse_type(const char* first,
>> const char
>> const char* t1 =
>> parse_template_args(t, last, db);
>> if (t1 != t)
>> {
>> - auto args =
>> db.names.back().move_full();
>> + auto args =
>> db.names.back();
>> db.names.pop_back();
>> - db.names.back().first += std::move(args);
>> - db.subs.push_back(Db::sub_type(1, db.names.back(),
>> db.names.get_allocator()));
>> + 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()));
>> t = t1;
>> }
>> }
>> @@ -2318,24 +3487,25 @@ parse_type(const char* first,
>> const char
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto type =
>> db.names.back().move_full();
>> + auto type =
>> db.names.back();
>> db.names.pop_back();
>> - if
>> (db.names.back().first.substr(0, 9) != "objcproto")
>> + if
>> (db.names.back()->K != Node::KNameType ||
>> +
>> !static_cast<NameType*>(db.names.back())->getName().startsWith("objcproto"))
>> {
>> - db.names.back() = type + " " + db.names.back().move_full();
>> + db.names.back() = db.make<VendorExtQualType>(type,
>> db.names.back());
>> }
>> else
>> {
>> - auto proto = db.names.back().move_full();
>> + auto* proto = static_cast<NameType*>(db.name
>> <http://db.name>s.back());
>> db.names.pop_back();
>> - t =
>> parse_source_name(proto.data() + 9, proto.data() +
>> proto.size(), db);
>> - if (t !=
>> proto.data() + 9)
>> + t =
>> parse_source_name(proto->getName().begin() + 9,
>> proto->getName().end(), db);
>> + if (t !=
>> proto->getName().begin() + 9)
>> {
>> - db.names.back() = type + "<" +
>> db.names.back().move_full() + ">";
>> + db.names.back() = db.make<ObjCProtoName>(type,
>> db.names.back());
>> }
>> else
>> {
>> - db.names.push_back(type + " " + proto);
>> + db.names.push_back(db.make<VendorExtQualType>(type,
>> proto));
>> }
>> }
>> db.subs.push_back(Db::sub_type(1, db.names.back(),
>> db.names.get_allocator()));
>> @@ -2371,9 +3541,11 @@ parse_type(const char* first,
>> const char
>> {
>> if
>> (db.names.size() < 2)
>> return first;
>> - auto template_args = db.names.back().move_full();
>> + auto template_args = db.names.back();
>> db.names.pop_back();
>> - db.names.back().first += template_args;
>> + db.names.back() = db.make<
>> + 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()));
>> first = t;
>> @@ -2520,20 +3692,20 @@ parse_operator_name(const char*
>> first, c
>> switch (first[1])
>> {
>> case 'a':
>> - db.names.push_back("operator&&");
>> + db.names.push_back(db.make<NameType>("operator&&"));
>> first += 2;
>> break;
>> case 'd':
>> case 'n':
>> - db.names.push_back("operator&");
>> + db.names.push_back(db.make<NameType>("operator&"));
>> first += 2;
>> break;
>> case 'N':
>> - db.names.push_back("operator&=");
>> + db.names.push_back(db.make<NameType>("operator&="));
>> first += 2;
>> break;
>> case 'S':
>> - db.names.push_back("operator=");
>> + db.names.push_back(db.make<NameType>("operator="));
>> first += 2;
>> break;
>> }
>> @@ -2542,15 +3714,15 @@ parse_operator_name(const char*
>> first, c
>> switch (first[1])
>> {
>> case 'l':
>> - db.names.push_back("operator()");
>> + db.names.push_back(db.make<NameType>("operator()"));
>> first += 2;
>> break;
>> case 'm':
>> - db.names.push_back("operator,");
>> + db.names.push_back(db.make<NameType>("operator,"));
>> first += 2;
>> break;
>> case 'o':
>> - db.names.push_back("operator~");
>> + db.names.push_back(db.make<NameType>("operator~"));
>> first += 2;
>> break;
>> case 'v':
>> @@ -2563,7 +3735,8 @@ parse_operator_name(const char*
>> first, c
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "operator ");
>> + db.names.back() =
>> + db.make<ConversionOperatorType>(db.names.back());
>> db.parsed_ctor_dtor_cv = true;
>> first = t;
>> }
>> @@ -2575,23 +3748,23 @@ parse_operator_name(const char*
>> first, c
>> switch (first[1])
>> {
>> case 'a':
>> - db.names.push_back("operator delete[]");
>> + db.names.push_back(db.make<NameType>("operator delete[]"));
>> first += 2;
>> break;
>> case 'e':
>> - db.names.push_back("operator*");
>> + db.names.push_back(db.make<NameType>("operator*"));
>> first += 2;
>> break;
>> case 'l':
>> - db.names.push_back("operator delete");
>> + db.names.push_back(db.make<NameType>("operator delete"));
>> first += 2;
>> break;
>> case 'v':
>> - db.names.push_back("operator/");
>> + db.names.push_back(db.make<NameType>("operator/"));
>> first += 2;
>> break;
>> case 'V':
>> - db.names.push_back("operator/=");
>> + db.names.push_back(db.make<NameType>("operator/="));
>> first += 2;
>> break;
>> }
>> @@ -2600,15 +3773,15 @@ parse_operator_name(const char*
>> first, c
>> switch (first[1])
>> {
>> case 'o':
>> - db.names.push_back("operator^");
>> + db.names.push_back(db.make<NameType>("operator^"));
>> first += 2;
>> break;
>> case 'O':
>> - db.names.push_back("operator^=");
>> + db.names.push_back(db.make<NameType>("operator^="));
>> first += 2;
>> break;
>> case 'q':
>> - db.names.push_back("operator==");
>> + db.names.push_back(db.make<NameType>("operator=="));
>> first += 2;
>> break;
>> }
>> @@ -2617,11 +3790,11 @@ parse_operator_name(const char*
>> first, c
>> switch (first[1])
>> {
>> case 'e':
>> - db.names.push_back("operator>=");
>> + db.names.push_back(db.make<NameType>("operator>="));
>> first += 2;
>> break;
>> case 't':
>> - db.names.push_back("operator>");
>> + db.names.push_back(db.make<NameType>("operator>"));
>> first += 2;
>> break;
>> }
>> @@ -2629,7 +3802,7 @@ parse_operator_name(const char*
>> first, c
>> case 'i':
>> if (first[1] == 'x')
>> {
>> - db.names.push_back("operator[]");
>> + db.names.push_back(db.make<NameType>("operator[]"));
>> first += 2;
>> }
>> break;
>> @@ -2637,7 +3810,7 @@ parse_operator_name(const char*
>> first, c
>> switch (first[1])
>> {
>> case 'e':
>> - db.names.push_back("operator<=");
>> + db.names.push_back(db.make<NameType>("operator<="));
>> first += 2;
>> break;
>> case 'i':
>> @@ -2647,21 +3820,22 @@ parse_operator_name(const char*
>> first, c
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "operator\"\" ");
>> + db.names.back() =
>> + db.make<LiteralOperator>(db.na <http://db.na>mes.back());
>> first = t;
>> }
>> }
>> break;
>> case 's':
>> - db.names.push_back("operator<<");
>> + db.names.push_back(db.make<NameType>("operator<<"));
>> first += 2;
>> break;
>> case 'S':
>> - db.names.push_back("operator<<=");
>> + db.names.push_back(db.make<NameType>("operator<<="));
>> first += 2;
>> break;
>> case 't':
>> - db.names.push_back("operator<");
>> + db.names.push_back(db.make<NameType>("operator<"));
>> first += 2;
>> break;
>> }
>> @@ -2670,23 +3844,23 @@ parse_operator_name(const char*
>> first, c
>> switch (first[1])
>> {
>> case 'i':
>> - db.names.push_back("operator-");
>> + db.names.push_back(db.make<NameType>("operator-"));
>> first += 2;
>> break;
>> case 'I':
>> - db.names.push_back("operator-=");
>> + db.names.push_back(db.make<NameType>("operator-="));
>> first += 2;
>> break;
>> case 'l':
>> - db.names.push_back("operator*");
>> + db.names.push_back(db.make<NameType>("operator*"));
>> first += 2;
>> break;
>> case 'L':
>> - db.names.push_back("operator*=");
>> + db.names.push_back(db.make<NameType>("operator*="));
>> first += 2;
>> break;
>> case 'm':
>> - db.names.push_back("operator--");
>> + db.names.push_back(db.make<NameType>("operator--"));
>> first += 2;
>> break;
>> }
>> @@ -2695,23 +3869,23 @@ parse_operator_name(const char*
>> first, c
>> switch (first[1])
>> {
>> case 'a':
>> - db.names.push_back("operator new[]");
>> + db.names.push_back(db.make<NameType>("operator new[]"));
>> first += 2;
>> break;
>> case 'e':
>> - db.names.push_back("operator!=");
>> + db.names.push_back(db.make<NameType>("operator!="));
>> first += 2;
>> break;
>> case 'g':
>> - db.names.push_back("operator-");
>> + db.names.push_back(db.make<NameType>("operator-"));
>> first += 2;
>> break;
>> case 't':
>> - db.names.push_back("operator!");
>> + db.names.push_back(db.make<NameType>("operator!"));
>> first += 2;
>> break;
>> case 'w':
>> - db.names.push_back("operator new");
>> + db.names.push_back(db.make<NameType>("operator new"));
>> first += 2;
>> break;
>> }
>> @@ -2720,15 +3894,15 @@ parse_operator_name(const char*
>> first, c
>> switch (first[1])
>> {
>> case 'o':
>> - db.names.push_back("operator||");
>> + db.names.push_back(db.make<NameType>("operator||"));
>> first += 2;
>> break;
>> case 'r':
>> - db.names.push_back("operator|");
>> + db.names.push_back(db.make<NameType>("operator|"));
>> first += 2;
>> break;
>> case 'R':
>> - db.names.push_back("operator|=");
>> + db.names.push_back(db.make<NameType>("operator|="));
>> first += 2;
>> break;
>> }
>> @@ -2737,27 +3911,27 @@ parse_operator_name(const char*
>> first, c
>> switch (first[1])
>> {
>> case 'm':
>> - db.names.push_back("operator->*");
>> + db.names.push_back(db.make<NameType>("operator->*"));
>> first += 2;
>> break;
>> case 'l':
>> - db.names.push_back("operator+");
>> + db.names.push_back(db.make<NameType>("operator+"));
>> first += 2;
>> break;
>> case 'L':
>> - db.names.push_back("operator+=");
>> + db.names.push_back(db.make<NameType>("operator+="));
>> first += 2;
>> break;
>> case 'p':
>> - db.names.push_back("operator++");
>> + db.names.push_back(db.make<NameType>("operator++"));
>> first += 2;
>> break;
>> case 's':
>> - db.names.push_back("operator+");
>> + db.names.push_back(db.make<NameType>("operator+"));
>> first += 2;
>> break;
>> case 't':
>> - db.names.push_back("operator->");
>> + db.names.push_back(db.make<NameType>("operator->"));
>> first += 2;
>> break;
>> }
>> @@ -2765,7 +3939,7 @@ parse_operator_name(const char*
>> first, c
>> case 'q':
>> if (first[1] == 'u')
>> {
>> - db.names.push_back("operator?");
>> + db.names.push_back(db.make<NameType>("operator?"));
>> first += 2;
>> }
>> break;
>> @@ -2773,19 +3947,19 @@ parse_operator_name(const char*
>> first, c
>> switch (first[1])
>> {
>> case 'm':
>> - db.names.push_back("operator%");
>> + db.names.push_back(db.make<NameType>("operator%"));
>> first += 2;
>> break;
>> case 'M':
>> - db.names.push_back("operator%=");
>> + db.names.push_back(db.make<NameType>("operator%="));
>> first += 2;
>> break;
>> case 's':
>> - db.names.push_back("operator>>");
>> + db.names.push_back(db.make<NameType>("operator>>"));
>> first += 2;
>> break;
>> case 'S':
>> - db.names.push_back("operator>>=");
>> + db.names.push_back(db.make<NameType>("operator>>="));
>> first += 2;
>> break;
>> }
>> @@ -2798,7 +3972,8 @@ parse_operator_name(const char*
>> first, c
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "operator ");
>> + db.names.back() =
>> + db.make<ConversionOperatorType>(db.names.back());
>> first = t;
>> }
>> }
>> @@ -2809,23 +3984,13 @@ parse_operator_name(const char*
>> first, c
>> }
>>
>> const char*
>> -parse_integer_literal(const char* first, const char*
>> last, const Db::String& lit, Db& db)
>> +parse_integer_literal(const char* first, const char*
>> last, StringView lit, Db& db)
>> {
>> const char* t = parse_number(first, last);
>> if (t != first && t != last && *t == 'E')
>> {
>> - if (lit.size() > 3)
>> - db.names.push_back("(" + lit + ")");
>> - else
>> - db.names.emplace_back();
>> - if (*first == 'n')
>> - {
>> - db.names.back().first += '-';
>> - ++first;
>> - }
>> - db.names.back().first.append(first, t);
>> - if (lit.size() <= 3)
>> - db.names.back().first += lit;
>> + db.names.push_back(
>> + db.make<IntegerExpr>(lit, StringView(first,
>> t)));
>> first = t+1;
>> }
>> return first;
>> @@ -2858,11 +4023,11 @@ parse_expr_primary(const char*
>> first, co
>> switch (first[2])
>> {
>> case '0':
>> - db.names.push_back("false");
>> + db.names.push_back(db.make<BoolExpr>(0));
>> first += 4;
>> break;
>> case '1':
>> - db.names.push_back("true");
>> + db.names.push_back(db.make<BoolExpr>(1));
>> first += 4;
>> break;
>> }
>> @@ -3007,7 +4172,8 @@ parse_expr_primary(const char*
>> first, co
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back() = "(" +
>> db.names.back().move_full() + ")" + Db::String(t, n);
>> + db.names.back() =
>> db.make<IntegerCastExpr>(
>> + db.names.back(), StringView(t, n));
>> first = n+1;
>> break;
>> }
>> @@ -3024,69 +4190,22 @@ parse_expr_primary(const char*
>> first, co
>> return first;
>> }
>>
>> -template <class String>
>> -String
>> -base_name(String& s)
>> +Node* maybe_change_special_sub_name(Node* inp, Db& db)
>> {
>> - if (s.empty())
>> - return s;
>> - if (s == "std::string")
>> - {
>> - s = "std::basic_string<char,
>> std::char_traits<char>, std::allocator<char> >";
>> - return "basic_string";
>> - }
>> - if (s == "std::istream")
>> - {
>> - s = "std::basic_istream<char,
>> std::char_traits<char> >";
>> - return "basic_istream";
>> - }
>> - if (s == "std::ostream")
>> - {
>> - s = "std::basic_ostream<char,
>> std::char_traits<char> >";
>> - return "basic_ostream";
>> - }
>> - if (s == "std::iostream")
>> - {
>> - s = "std::basic_iostream<char,
>> std::char_traits<char> >";
>> - return "basic_iostream";
>> - }
>> - const char* const pf = s.data();
>> - const char* pe = pf + s.size();
>> - if (pe[-1] == '>')
>> - {
>> - unsigned c = 1;
>> - while (true)
>> - {
>> - if (--pe == pf)
>> - return String();
>> - if (pe[-1] == '<')
>> - {
>> - if (--c == 0)
>> - {
>> - --pe;
>> - break;
>> - }
>> - }
>> - else if (pe[-1] == '>')
>> - ++c;
>> - }
>> + if (inp->K != Node::KSpecialSubstitution)
>> + return inp;
>> + auto Kind = static_cast<SpecialSubstitution*>(inp)->SSK;
>> + switch (Kind)
>> + {
>> + case SpecialSubKind::string:
>> + case SpecialSubKind::istream:
>> + case SpecialSubKind::ostream:
>> + case SpecialSubKind::iostream:
>> + return db.make<ExpandedSpecialSubstitution>(Kind);
>> + default:
>> + break;
>> }
>> - if (pe - pf <= 1)
>> - return String();
>> - const char* p0 = pe - 1;
>> - for (; p0 != pf; --p0)
>> - {
>> - if (*p0 == ':')
>> - {
>> - ++p0;
>> - break;
>> - }
>> - if (!isalpha(*p0) && !isdigit(*p0) && *p0 != '_')
>> - {
>> - return String();
>> - }
>> - }
>> - return String(p0, pe);
>> + return inp;
>> }
>>
>> // <ctor-dtor-name> ::= C1 # complete object constructor
>> @@ -3114,7 +4233,10 @@ parse_ctor_dtor_name(const char*
>> first,
>> case '5':
>> if (db.names.empty())
>> return first;
>> - db.names.push_back(base_name(db.names.back().first));
>> + db.names.back() =
>> + maybe_change_special_sub_name(db.names.back(), db);
>> + db.names.push_back(
>> + db.make<CtorDtorName>(db.names.back(), false));
>> first += 2;
>> db.parsed_ctor_dtor_cv = true;
>> break;
>> @@ -3129,7 +4251,8 @@ parse_ctor_dtor_name(const char* first,
>> case '5':
>> if (db.names.empty())
>> return first;
>> - db.names.push_back("~" +
>> base_name(db.names.back().first));
>> + db.names.push_back(
>> + db.make<CtorDtorName>(db.names.back(), true));
>> first += 2;
>> db.parsed_ctor_dtor_cv = true;
>> break;
>> @@ -3157,106 +4280,63 @@ parse_unnamed_type_name(const
>> char* firs
>> {
>> case 't':
>> {
>> - db.names.push_back(Db::String("'unnamed"));
>> const char* t0 = first+2;
>> if (t0 == last)
>> - {
>> - db.names.pop_back();
>> return first;
>> - }
>> + StringView count;
>> if (std::isdigit(*t0))
>> {
>> const char* t1 = t0 + 1;
>> while (t1 != last && std::isdigit(*t1))
>> ++t1;
>> - db.names.back().first.append(t0, t1);
>> + count = StringView(t0, t1);
>> t0 = t1;
>> }
>> - db.names.back().first.push_back('\'');
>> if (t0 == last || *t0 != '_')
>> - {
>> - db.names.pop_back();
>> return first;
>> - }
>> + db.names.push_back(db.make<UnnamedTypeName>(count));
>> first = t0 + 1;
>> }
>> break;
>> case 'l':
>> {
>> - size_t lambda_pos = db.names.size();
>> - db.names.push_back(Db::String("'lambda'("));
>> + size_t begin_pos = db.names.size();
>> const char* t0 = first+2;
>> + NodeArray lambda_params;
>> if (first[2] == 'v')
>> {
>> - db.names.back().first += ')';
>> ++t0;
>> }
>> else
>> {
>> - bool is_first_it = true;
>> while (true)
>> {
>> - 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 (k0 >= k1)
>> - return first;
>> - // 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,
>> - [&](Db::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 (is_first_it)
>> - {
>> - if (!db.names.empty())
>> - db.names.pop_back();
>> + if (db.names.size() < begin_pos)
>> return first;
>> - }
>> - if (db.names.empty() || db.names.size()
>> - 1 != lambda_pos)
>> - return first;
>> - db.names.back().first.append(")");
>> + lambda_params =
>> db.popTrailingNodeArray(begin_pos);
>> }
>> if (t0 == last || *t0 != 'E')
>> - {
>> - if (!db.names.empty())
>> - db.names.pop_back();
>> - return first;
>> - }
>> + return first;
>> ++t0;
>> if (t0 == last)
>> - {
>> - if(!db.names.empty())
>> - db.names.pop_back();
>> return first;
>> - }
>> + StringView count;
>> if (std::isdigit(*t0))
>> {
>> const char* t1 = t0 + 1;
>> while (t1 != last && std::isdigit(*t1))
>> ++t1;
>> -
>> db.names.back().first.insert(db.names.back().first.begin()+7,
>> t0, t1);
>> + count = StringView(t0, t1);
>> t0 = t1;
>> }
>> if (t0 == last || *t0 != '_')
>> - {
>> - if(!db.names.empty())
>> - db.names.pop_back();
>> return first;
>> - }
>> +
>> db.names.push_back(db.make<LambdaTypeName>(lambda_params,
>> count));
>> first = t0 + 1;
>> }
>> break;
>> @@ -3337,7 +4417,8 @@ parse_unscoped_name(const char*
>> first, c
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "std::");
>> + db.names.back() =
>> + db.make<StdQualifiedName>(db.names.back());
>> }
>> first = t1;
>> }
>> @@ -3357,7 +4438,8 @@ parse_alignof_type(const char*
>> first, co
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first = "alignof (" +
>> db.names.back().move_full() + ")";
>> + db.names.back() =
>> + db.make<EnclosingExpr>("alignof (", db.names.back(), ")");
>> first = t;
>> }
>> }
>> @@ -3376,7 +4458,8 @@ parse_alignof_expr(const char*
>> first, co
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first = "alignof (" +
>> db.names.back().move_full() + ")";
>> + db.names.back() =
>> + db.make<EnclosingExpr>("alignof (", db.names.back(), ")");
>> first = t;
>> }
>> }
>> @@ -3391,28 +4474,29 @@ parse_noexcept_expression(const
>> char* fi
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first = "noexcept (" +
>> db.names.back().move_full() + ")";
>> + db.names.back() =
>> + db.make<EnclosingExpr>("noexcept (", db.names.back(), ")");
>> first = t1;
>> }
>> return first;
>> }
>>
>> const char*
>> -parse_prefix_expression(const char* first, const char*
>> last, const Db::String& op, Db& db)
>> +parse_prefix_expression(const char* first, const char*
>> last, StringView op, Db& db)
>> {
>> const char* t1 = parse_expression(first, last, db);
>> if (t1 != first)
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first = op + "(" +
>> db.names.back().move_full() + ")";
>> + db.names.back() = db.make<PrefixExpr>(op,
>> db.names.back());
>> first = t1;
>> }
>> return first;
>> }
>>
>> const char*
>> -parse_binary_expression(const char* first, const char*
>> last, const Db::String& op, Db& db)
>> +parse_binary_expression(const char* first, const char*
>> last, StringView op, Db& db)
>> {
>> const char* t1 = parse_expression(first, last, db);
>> if (t1 != first)
>> @@ -3422,20 +4506,12 @@ parse_binary_expression(const
>> char* firs
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto op2 = db.names.back().move_full();
>> + auto op2 = db.names.back();
>> db.names.pop_back();
>> - auto op1 = db.names.back().move_full();
>> - auto& nm = db.names.back().first;
>> - nm.clear();
>> - if (op == ">")
>> - nm += '(';
>> - nm += "(" + op1 + ") " + op + " (" + op2 + ")";
>> - if (op == ">")
>> - nm += ')';
>> + auto op1 = db.names.back();
>> + db.names.back() = db.make<BinaryExpr>(op1,
>> op, op2);
>> first = t2;
>> }
>> - else if(!db.names.empty())
>> - db.names.pop_back();
>> }
>> return first;
>> }
>> @@ -3573,8 +4649,8 @@ parse_expression(const char* first,
>> cons
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first = (parsed_gs ? Db::String("::") :
>> Db::String()) +
>> - "delete[] " + db.names.back().move_full();
>> + db.names.back() =
>> db.make<DeleteExpr>(
>> + db.names.back(), parsed_gs, /*is_array=*/true);
>> first = t1;
>> }
>> }
>> @@ -3594,8 +4670,8 @@ parse_expression(const char* first,
>> cons
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first = (parsed_gs ? Db::String("::") :
>> Db::String()) +
>> - "delete " + db.names.back().move_full();
>> + db.names.back() =
>> db.make<DeleteExpr>(
>> + db.names.back(), parsed_gs, /*is_array=*/false);
>> first = t1;
>> }
>> }
>> @@ -3666,10 +4742,11 @@ parse_expression(const char*
>> first, cons
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto op2 =
>> db.names.back().move_full();
>> + auto op2 = db.names.back();
>> db.names.pop_back();
>> - auto op1 =
>> db.names.back().move_full();
>> - db.names.back() = "(" + op1 +
>> ")[" + op2 + "]";
>> + auto op1 = db.names.back();
>> + db.names.back() =
>> + db.make<ArraySubscriptExpr>(op1, op2);
>> first = t2;
>> }
>> else if (!db.names.empty())
>> @@ -3739,7 +4816,8 @@ parse_expression(const char* first,
>> cons
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back() = "(" +
>> db.names.back().move_full() + ")--";
>> + db.names.back() =
>> + db.make<PostfixExpr>(db.names.back(), "--");
>> first = t1;
>> }
>> }
>> @@ -3829,7 +4907,8 @@ parse_expression(const char* first,
>> cons
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back() = "(" +
>> db.names.back().move_full() + ")++";
>> + db.names.back() =
>> + db.make<PostfixExpr>(db.names.back(), "++");
>> first = t1;
>> }
>> }
>> @@ -3858,12 +4937,13 @@ parse_expression(const char*
>> first, cons
>> {
>> if (db.names.size() < 3)
>> return first;
>> - auto op3 =
>> db.names.back().move_full();
>> + auto op3 = db.names.back();
>> db.names.pop_back();
>> - auto op2 =
>> db.names.back().move_full();
>> + auto op2 = db.names.back();
>> db.names.pop_back();
>> - auto op1 =
>> db.names.back().move_full();
>> - db.names.back() = "(" + op1
>> + ") ? (" + op2 + ") : (" + op3 + ")";
>> + auto op1 = db.names.back();
>> + db.names.back() =
>> + db.make<ConditionalExpr>(op1, op2, op3);
>> first = t3;
>> }
>> else
>> @@ -3948,7 +5028,7 @@ parse_expression(const char* first,
>> cons
>> first = parse_typeid_expr(first, last, db);
>> break;
>> case 'r':
>> - db.names.push_back("throw");
>> + db.names.push_back(db.make<NameType>("throw"));
>> first += 2;
>> break;
>> case 'w':
>> @@ -4037,7 +5117,7 @@ parse_template_args(const char*
>> first, c
>> if (db.tag_templates)
>> db.template_param.back().clear();
>> const char* t = first+1;
>> - Db::String args("<");
>> + size_t begin_idx = db.names.size();
>> while (*t != 'E')
>> {
>> if (db.tag_templates)
>> @@ -4047,7 +5127,7 @@ parse_template_args(const char*
>> first, c
>> size_t k1 = db.names.size();
>> if (db.tag_templates)
>> db.template_param.pop_back();
>> - if (t1 == t || t1 == last)
>> + if (t1 == t || t1 == last || k0 > k1)
>> return first;
>> if (db.tag_templates)
>> {
>> @@ -4055,30 +5135,18 @@ parse_template_args(const char*
>> first, c
>> for (size_t k = k0; k < k1; ++k)
>> db.template_param.back().back().push_back(db.names[k]);
>> }
>> - for (size_t k = k0; k < k1; ++k)
>> - {
>> - if (args.size() > 1)
>> - args += ", ";
>> - args += db.names[k].move_full();
>> - }
>> - for (; k1 > k0; --k1)
>> - if (!db.names.empty())
>> - db.names.pop_back();
>> t = t1;
>> }
>> first = t + 1;
>> - if (args.back() != '>')
>> - args += ">";
>> - else
>> - args += " >";
>> - db.names.push_back(std::move(args));
>> -
>> + TemplateParams* tp = db.make<TemplateParams>(
>> + db.popTrailingNodeArray(begin_idx));
>> + db.names.push_back(tp);
>> }
>> return first;
>> }
>>
>> -// <nested-name> ::= N [<CV-qualifiers>]
>> [<ref-qualifier>] <prefix> <unqualified-name> E
>> -// ::= N [<CV-qualifiers>]
>> [<ref-qualifier>] <template-prefix> <template-args> E
>> +// <nested-name> ::= N [<CV-Qualifiers>]
>> [<ref-qualifier>] <prefix> <unqualified-name> E
>> +// ::= N [<CV-Qualifiers>]
>> [<ref-qualifier>] <template-prefix> <template-args> E
>> //
>> // <prefix> ::= <prefix> <unqualified-name>
>> // ::= <template-prefix> <template-args>
>> @@ -4099,32 +5167,29 @@ parse_nested_name(const char*
>> first, con
>> {
>> if (first != last && *first == 'N')
>> {
>> - unsigned cv;
>> + Qualifiers cv;
>> const char* t0 = parse_cv_qualifiers(first+1,
>> last, cv);
>> if (t0 == last)
>> return first;
>> - db.ref = 0;
>> + db.ref = FrefQualNone;
>> if (*t0 == 'R')
>> {
>> - db.ref = 1;
>> + db.ref = FrefQualLValue;
>> ++t0;
>> }
>> else if (*t0 == 'O')
>> {
>> - db.ref = 2;
>> + db.ref = FrefQualRValue;
>> ++t0;
>> }
>> - db.names.emplace_back();
>> + db.names.push_back(db.make<EmptyName>());
>> if (last - t0 >= 2 && t0[0] == 'S' && t0[1] == 't')
>> {
>> t0 += 2;
>> - db.names.back().first = "std";
>> + db.names.back() = db.make<NameType>("std");
>> }
>> if (t0 == last)
>> - {
>> - db.names.pop_back();
>> return first;
>> - }
>> bool pop_subs = false;
>> bool component_ends_with_template_args = false;
>> while (*t0 != 'E')
>> @@ -4139,17 +5204,18 @@ parse_nested_name(const char*
>> first, con
>> t1 = parse_substitution(t0, last, db);
>> if (t1 != t0 && t1 != last)
>> {
>> - auto name = db.names.back().move_full();
>> + auto name = db.names.back();
>> db.names.pop_back();
>> - if (db.names.empty())
>> - return first;
>> - if (!db.names.back().first.empty())
>> + if (db.names.back()->K !=
>> Node::KEmptyName)
>> {
>> - db.names.back().first += "::" + name;
>> - db.subs.push_back(Db::sub_type(1, db.names.back(),
>> db.names.get_allocator()));
>> + 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()));
>> }
>> else
>> - db.names.back().first = name;
>> + db.names.back() = name;
>> pop_subs = true;
>> t0 = t1;
>> }
>> @@ -4160,14 +5226,13 @@ parse_nested_name(const char*
>> first, con
>> t1 = parse_template_param(t0, last, db);
>> if (t1 != t0 && t1 != last)
>> {
>> - auto name = db.names.back().move_full();
>> + auto name = db.names.back();
>> db.names.pop_back();
>> - if (db.names.empty())
>> - return first;
>> - if (!db.names.back().first.empty())
>> - db.names.back().first += "::" + name;
>> + if (db.names.back()->K !=
>> Node::KEmptyName)
>> + db.names.back() =
>> + db.make<QualifiedName>(db.name
>> <http://db.name>s.back(), name);
>> else
>> - db.names.back().first = name;
>> + db.names.back() = name;
>> db.subs.push_back(Db::sub_type(1, db.names.back(),
>> db.names.get_allocator()));
>> pop_subs = true;
>> t0 = t1;
>> @@ -4181,14 +5246,13 @@ parse_nested_name(const char*
>> first, con
>> t1 = parse_decltype(t0, last, db);
>> if (t1 != t0 && t1 != last)
>> {
>> - auto name = db.names.back().move_full();
>> + auto name = db.names.back();
>> db.names.pop_back();
>> - if (db.names.empty())
>> - return first;
>> - if (!db.names.back().first.empty())
>> - db.names.back().first += "::" + name;
>> + if (db.names.back()->K !=
>> Node::KEmptyName)
>> + db.names.back() =
>> + db.make<QualifiedName>(db.name
>> <http://db.name>s.back(), name);
>> else
>> - db.names.back().first = name;
>> + db.names.back() = name;
>> db.subs.push_back(Db::sub_type(1, db.names.back(),
>> db.names.get_allocator()));
>> pop_subs = true;
>> t0 = t1;
>> @@ -4200,12 +5264,12 @@ parse_nested_name(const char*
>> first, con
>> t1 = parse_template_args(t0, last, db);
>> if (t1 != t0 && t1 != last)
>> {
>> - auto name = db.names.back().move_full();
>> + auto name = db.names.back();
>> db.names.pop_back();
>> - if (db.names.empty())
>> - return first;
>> - db.names.back().first += name;
>> - db.subs.push_back(Db::sub_type(1, db.names.back(),
>> db.names.get_allocator()));
>> + 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()));
>> t0 = t1;
>> component_ends_with_template_args = true;
>> }
>> @@ -4221,14 +5285,13 @@ parse_nested_name(const char*
>> first, con
>> t1 = parse_unqualified_name(t0, last, db);
>> if (t1 != t0 && t1 != last)
>> {
>> - auto name = db.names.back().move_full();
>> + auto name = db.names.back();
>> db.names.pop_back();
>> - if (db.names.empty())
>> - return first;
>> - if (!db.names.back().first.empty())
>> - db.names.back().first += "::" + name;
>> + if (db.names.back()->K !=
>> Node::KEmptyName)
>> + db.names.back() =
>> + db.make<QualifiedName>(db.name
>> <http://db.name>s.back(), name);
>> else
>> - db.names.back().first = name;
>> + db.names.back() = name;
>> db.subs.push_back(Db::sub_type(1, db.names.back(),
>> db.names.get_allocator()));
>> pop_subs = true;
>> t0 = t1;
>> @@ -4304,7 +5367,8 @@ parse_local_name(const char* first,
>> cons
>> first = parse_discriminator(t+1, last);
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.append("::string literal");
>> + db.names.back() = db.make<QualifiedName>(
>> + db.names.back(),
>> db.make<NameType>("string literal"));
>> break;
>> case 'd':
>> if (++t != last)
>> @@ -4319,12 +5383,12 @@ parse_local_name(const char*
>> first, cons
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto name =
>> db.names.back().move_full();
>> + auto name = db.names.back();
>> db.names.pop_back();
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.append("::");
>> - db.names.back().first.append(name);
>> + db.names.back() =
>> + db.make<QualifiedName>(db.name
>> <http://db.name>s.back(), name);
>> first = t1;
>> }
>> else if (!db.names.empty())
>> @@ -4342,12 +5406,12 @@ parse_local_name(const char*
>> first, cons
>> first = parse_discriminator(t1,
>> last);
>> if (db.names.size() < 2)
>> return first;
>> - auto name =
>> db.names.back().move_full();
>> + auto name = db.names.back();
>> db.names.pop_back();
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.append("::");
>> - db.names.back().first.append(name);
>> + db.names.back() =
>> + db.make<QualifiedName>(db.name
>> <http://db.name>s.back(), name);
>> }
>> else if (!db.names.empty())
>> db.names.pop_back();
>> @@ -4411,11 +5475,13 @@ parse_name(const char* first,
>> const char
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto tmp =
>> db.names.back().move_full();
>> + auto tmp = db.names.back();
>> db.names.pop_back();
>> if (db.names.empty())
>> return first;
>> - db.names.back().first += tmp;
>> + db.names.back() =
>> + db.make<NameWithTemplateArgs>(
>> + db.names.back(), tmp);
>> first = t1;
>> if (ends_with_template_args)
>> *ends_with_template_args = true;
>> @@ -4435,11 +5501,13 @@ parse_name(const char* first,
>> const char
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto tmp =
>> db.names.back().move_full();
>> + auto tmp = db.names.back();
>> db.names.pop_back();
>> if (db.names.empty())
>> return first;
>> - db.names.back().first += tmp;
>> + db.names.back() =
>> + db.make<NameWithTemplateArgs>(
>> + db.names.back(), tmp);
>> first = t1;
>> if (ends_with_template_args)
>> *ends_with_template_args = true;
>> @@ -4527,7 +5595,8 @@ parse_special_name(const char*
>> first, co
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "vtable for ");
>> + db.names.back() =
>> + db.make<SpecialName>("vtable for ", db.names.back());
>> first = t;
>> }
>> break;
>> @@ -4538,7 +5607,8 @@ parse_special_name(const char*
>> first, co
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "VTT for ");
>> + db.names.back() =
>> + db.make<SpecialName>("VTT for ", db.names.back());
>> first = t;
>> }
>> break;
>> @@ -4549,7 +5619,8 @@ parse_special_name(const char*
>> first, co
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "typeinfo for ");
>> + db.names.back() =
>> + db.make<SpecialName>("typeinfo for ", db.names.back());
>> first = t;
>> }
>> break;
>> @@ -4560,7 +5631,8 @@ parse_special_name(const char*
>> first, co
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "typeinfo name for ");
>> + db.names.back() =
>> + db.make<SpecialName>("typeinfo name for ",
>> db.names.back());
>> first = t;
>> }
>> break;
>> @@ -4578,7 +5650,9 @@ parse_special_name(const char*
>> first, co
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "covariant return thunk
>> to ");
>> + db.names.back() =
>> + db.make<SpecialName>("covariant return thunk to ",
>> + db.names.back());
>> first = t;
>> }
>> }
>> @@ -4596,13 +5670,12 @@ parse_special_name(const char*
>> first, co
>> {
>> if (db.names.size() < 2)
>> return first;
>> - auto left =
>> db.names.back().move_full();
>> + auto left = db.names.back();
>> db.names.pop_back();
>> if (db.names.empty())
>> return first;
>> - db.names.back().first = "construction vtable for " +
>> - std::move(left) + "-in-" +
>> - db.names.back().move_full();
>> + db.names.back() =
>> db.make<CtorVtableSpecialName>(
>> + left, db.names.back());
>> first = t1;
>> }
>> }
>> @@ -4614,8 +5687,10 @@ parse_special_name(const char*
>> first, co
>> if (t != first + 2)
>> {
>> if (db.names.empty())
>> - return first;
>> - db.names.back().first.insert(0, "thread-local wrapper
>> routine for ");
>> + return first;
>> + db.names.back() =
>> + db.make<SpecialName>("thread-local wrapper routine for ",
>> + db.names.back());
>> first = t;
>> }
>> break;
>> @@ -4625,8 +5700,9 @@ parse_special_name(const char*
>> first, co
>> if (t != first + 2)
>> {
>> if (db.names.empty())
>> - return first;
>> - db.names.back().first.insert(0, "thread-local
>> initialization routine for ");
>> + return first;
>> + db.names.back() = db.make<SpecialName>(
>> + "thread-local initialization
>> routine for ", db.names.back());
>> first = t;
>> }
>> break;
>> @@ -4643,12 +5719,16 @@ parse_special_name(const char*
>> first, co
>> return first;
>> if (first[1] == 'v')
>> {
>> - db.names.back().first.insert(0, "virtual thunk to ");
>> + db.names.back() =
>> + db.make<SpecialName>("virtual thunk to ",
>> + db.names.back());
>> first = t;
>> }
>> else
>> {
>> - db.names.back().first.insert(0, "non-virtual thunk to ");
>> + db.names.back() =
>> + db.make<SpecialName>("non-virtual thunk to ",
>> + db.names.back());
>> first = t;
>> }
>> }
>> @@ -4666,7 +5746,8 @@ parse_special_name(const char*
>> first, co
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "guard variable for ");
>> + db.names.back() =
>> + db.make<SpecialName>("guard variable for ",
>> db.names.back());
>> first = t;
>> }
>> break;
>> @@ -4677,7 +5758,9 @@ parse_special_name(const char*
>> first, co
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "reference temporary
>> for ");
>> + db.names.back() =
>> + db.make<SpecialName>("reference temporary for ",
>> + db.names.back());
>> first = t;
>> }
>> break;
>> @@ -4735,8 +5818,10 @@ parse_encoding(const char* first,
>> const
>> bool ends_with_template_args = false;
>> const char* t = parse_name(first, last, db,
>> &ends_with_template_args);
>> - unsigned cv = db.cv <http://db.cv>;
>> - unsigned ref = db.ref;
>> + if (db.names.empty())
>> + return first;
>> + Qualifiers cv = db.cv <http://db.cv>;
>> + FunctionRefQual ref = db.ref;
>> if (t != first)
>> {
>> if (t != last && *t != 'E' && *t != '.')
>> @@ -4744,87 +5829,59 @@ parse_encoding(const char* first,
>> const
>> save_value<bool> sb2(db.tag_templates);
>> db.tag_templates = false;
>> const char* t2;
>> - Db::String ret2;
>> if (db.names.empty())
>> return first;
>> - const Db::String& nm =
>> db.names.back().first;
>> - if (nm.empty())
>> + if (!db.names.back())
>> return first;
>> + Node* return_type = nullptr;
>> if (!db.parsed_ctor_dtor_cv &&
>> ends_with_template_args)
>> {
>> t2 = parse_type(t, last, db);
>> if (t2 == t)
>> return first;
>> - if (db.names.size() < 2)
>> + if (db.names.size() < 1)
>> return first;
>> - auto ret1 =
>> std::move(db.names.back().first);
>> - ret2 =
>> std::move(db.names.back().second);
>> - if (ret2.empty())
>> - ret1 += ' ';
>> + return_type = db.names.back();
>> db.names.pop_back();
>> - if (db.names.empty())
>> - return first;
>> -
>> - db.names.back().first.insert(0, ret1);
>> t = t2;
>> }
>> - db.names.back().first += '(';
>> +
>> + Node* result = nullptr;
>> +
>> if (t != last && *t == 'v')
>> {
>> ++t;
>> + Node* name = db.names.back();
>> + db.names.pop_back();
>> + result =
>> db.make<TopLevelFunctionDecl>(
>> + return_type, name, NodeArray());
>> }
>> else
>> {
>> - bool first_arg = true;
>> + size_t params_begin =
>> db.names.size();
>> while (true)
>> {
>> - size_t k0 = db.names.size();
>> t2 = parse_type(t, last, db);
>> - size_t k1 = db.names.size();
>> if (t2 == t)
>> break;
>> - if (k1 > k0)
>> - {
>> - Db::String tmp;
>> - for (size_t k = k0; k <
>> k1; ++k)
>> - {
>> - if (!tmp.empty())
>> - tmp += ", ";
>> - tmp +=
>> db.names[k].move_full();
>> - }
>> - for (size_t k = k0; k <
>> k1; ++k) {
>> - if (db.names.empty())
>> - return first;
>> - db.names.pop_back();
>> - }
>> - if (!tmp.empty())
>> - {
>> - if (db.names.empty())
>> - return first;
>> - if (!first_arg)
>> - db.names.back().first += ", ";
>> - else
>> - first_arg = false;
>> - db.names.back().first += tmp;
>> - }
>> - }
>> t = t2;
>> }
>> + if (db.names.size() < params_begin)
>> + return first;
>> + NodeArray params =
>> + db.popTrailingNodeArray(params_begin);
>> + if (db.names.empty())
>> + return first;
>> + Node* name = db.names.back();
>> + db.names.pop_back();
>> + result =
>> db.make<TopLevelFunctionDecl>(
>> + return_type, name, params);
>> }
>> - if (db.names.empty())
>> - return first;
>> - db.names.back().first += ')';
>> - if (cv & 1)
>> - db.names.back().first.append(" const");
>> - if (cv & 2)
>> - db.names.back().first.append(" volatile");
>> - if (cv & 4)
>> - db.names.back().first.append(" restrict");
>> - if (ref == 1)
>> - db.names.back().first.append(" &");
>> - else if (ref == 2)
>> - db.names.back().first.append(" &&");
>> - db.names.back().first += ret2;
>> + if (ref != FrefQualNone)
>> + result =
>> db.make<FunctionRefQualType>(result, ref);
>> + if (cv != QualNone)
>> + result =
>> db.make<FunctionQualType>(result, cv);
>> + db.names.push_back(result);
>> first = t;
>> }
>> else
>> @@ -4846,6 +5903,7 @@ parse_block_invoke(const char*
>> first, co
>> {
>> if (last - first >= 13)
>> {
>> + // FIXME: strcmp?
>> const char test[] = "_block_invoke";
>> const char* t = first;
>> for (int i = 0; i < 13; ++i, ++t)
>> @@ -4868,7 +5926,9 @@ parse_block_invoke(const char*
>> first, co
>> }
>> if (db.names.empty())
>> return first;
>> - db.names.back().first.insert(0, "invocation
>> function for block in ");
>> + db.names.back() =
>> + db.make<SpecialName>("invocation function for block in ",
>> + db.names.back());
>> first = t;
>> }
>> return first;
>> @@ -4884,7 +5944,8 @@ parse_dot_suffix(const char* first,
>> cons
>> {
>> if (db.names.empty())
>> return first;
>> - db.names.back().first += " (" +
>> Db::String(first, last) + ")";
>> + db.names.back() =
>> + db.make<DotSuffix>(db.names.ba
>> <http://db.names.ba>ck(), StringView(first, last));
>> first = last;
>> }
>> return first;
>> @@ -4963,6 +6024,7 @@ __cxa_demangle(const char
>> *mangled_name,
>> size_t len = std::strlen(mangled_name);
>> demangle(mangled_name, mangled_name + len, db,
>> internal_status);
>> +
>> if (internal_status == success &&
>> db.fix_forward_references &&
>> !db.template_param.empty() &&
>> !db.template_param.front().empty())
>> {
>> @@ -4974,30 +6036,25 @@ __cxa_demangle(const char
>> *mangled_name,
>> if (db.fix_forward_references)
>> internal_status = invalid_mangled_name;
>> }
>> +
>> if (internal_status == success)
>> {
>> - size_t sz = db.names.back().size() + 1;
>> - if (sz > internal_size)
>> + if (!buf)
>> {
>> - char* newbuf =
>> static_cast<char*>(std::realloc(buf, sz));
>> - if (newbuf == nullptr)
>> - {
>> - internal_status = memory_alloc_failure;
>> - buf = nullptr;
>> - }
>> - else
>> - {
>> - buf = newbuf;
>> - if (n != nullptr)
>> - *n = sz;
>> - }
>> + internal_size = 1024;
>> + buf =
>> static_cast<char*>(std::malloc(internal_size));
>> }
>> - if (buf != nullptr)
>> +
>> + if (buf)
>> {
>> - db.names.back().first += db.names.back().second;
>> - std::memcpy(buf,
>> db.names.back().first.data(), sz-1);
>> - buf[sz-1] = char(0);
>> + 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;
>>
>> Modified: libcxxabi/trunk/test/test_demangle.pass.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/test_demangle.pass.cpp?rev=309340&r1=309339&r2=309340&view=diff
>> <http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/test_demangle.pass.cpp?rev=309340&r1=309339&r2=309340&view=diff>
>> ==============================================================================
>> --- libcxxabi/trunk/test/test_demangle.pass.cpp (original)
>> +++ libcxxabi/trunk/test/test_demangle.pass.cpp Thu Jul
>> 27 17:43:49 2017
>> @@ -29600,8 +29600,7 @@ const char* cases[][2] =
>> {"i", "int"},
>>
>> {"PKFvRiE", "void (*)(int&) const"},
>> - // FIXME(compnerd) pretty print this as void
>> (*)(unsigned long &) volatile &&
>> - {"PVFvRmOE", "void (*)(unsigned long&) volatile&&"},
>> + {"PVFvRmOE", "void (*)(unsigned long&) volatile &&"},
>> {"PFvRmOE", "void (*)(unsigned long&) &&"},
>> {"_ZTW1x", "thread-local wrapper routine for x"},
>> {"_ZTHN3fooE", "thread-local initialization routine
>> for foo"},
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> <mailto:cfe-commits at lists.llvm.org>
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>> <http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits>
>>
>>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170806/cd2becb5/attachment-0001.html>
More information about the cfe-commits
mailing list