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