erik.pilkington updated this revision to Diff 131535.
erik.pilkington marked 2 inline comments as done.
erik.pilkington added a comment.
In this new patch:
- Make the cached values use a 3-way bool type, and default it to false. This
simplifies all the Node ctors.
- Remove some minor style fixes to clean up the diff.
https://reviews.llvm.org/D41885
Files:
src/cxa_demangle.cpp
test/test_demangle.pass.cpp
test/unittest_demangle.pass.cpp
Index: test/unittest_demangle.pass.cpp
===================================================================
--- test/unittest_demangle.pass.cpp
+++ test/unittest_demangle.pass.cpp
@@ -82,44 +82,6 @@
}
}
-void testSubstitutionTable() {
- {
- SubstitutionTable<2> Tab;
-
- NameType Names[] = {{"MERP"}, {"MARP"}, {"MAMP"}};
- Tab.pushPack();
- Tab.pushSubstitutionIntoPack(&Names[0]);
- Tab.pushSubstitutionIntoPack(&Names[1]);
- Tab.pushSubstitutionIntoPack(&Names[2]);
-
- int Index = 0;
- for (Node* N : Tab.nthSubstitution(0)) {
- assert(static_cast<NameType*>(N)->getName() == Names[Index].getName());
- ++Index;
- }
- assert(Index == 3);
-
- Tab.popPack();
- assert(Tab.empty() && Tab.size() == 0);
- Tab.pushSubstitution(&Names[0]);
- Tab.pushSubstitution(&Names[1]);
- assert(!Tab.empty() && Tab.size() == 2);
-
- int I = 0;
- for (Node* N : Tab.nthSubstitution(0)) {
- assert(static_cast<NameType*>(N)->getName() == "MERP");
- assert(I == 0);
- ++I;
- }
- for (Node* N : Tab.nthSubstitution(1)) {
- assert(static_cast<NameType*>(N)->getName() == "MARP");
- assert(I == 1);
- ++I;
- }
- }
-}
-
int main() {
testPODSmallVector();
- testSubstitutionTable();
}
Index: test/test_demangle.pass.cpp
===================================================================
--- test/test_demangle.pass.cpp
+++ test/test_demangle.pass.cpp
@@ -29585,7 +29585,7 @@
{"_Z1fPU11objcproto1A11objc_object", "f(id<A>)"},
{"_Z1fPKU11objcproto1A7NSArray", "f(NSArray<A> const*)"},
{"_ZNK1AIJ1Z1Y1XEEcv1BIJDpPT_EEIJS2_S1_S0_EEEv", "A<Z, Y, X>::operator B<X*, Y*, Z*><X, Y, Z>() const"},
- {"_ZNK3Ncr6Silver7Utility6detail12CallOnThreadIZ53-[DeploymentSetupController handleManualServerEntry:]E3$_5EclIJEEEDTclclL_ZNS2_4getTIS4_EERT_vEEspclsr3stdE7forwardIT_Efp_EEEDpOSA_", "decltype(-[DeploymentSetupController handleManualServerEntry:]::$_5& Ncr::Silver::Utility::detail::getT<-[DeploymentSetupController handleManualServerEntry:]::$_5>()()(std::forward<-[DeploymentSetupController handleManualServerEntry:]::$_5>(fp))) Ncr::Silver::Utility::detail::CallOnThread<-[DeploymentSetupController handleManualServerEntry:]::$_5>::operator()<>(-[DeploymentSetupController handleManualServerEntry:]::$_5&&) const"},
+ {"_ZNK3Ncr6Silver7Utility6detail12CallOnThreadIZ53-[DeploymentSetupController handleManualServerEntry:]E3$_5EclIJEEEDTclclL_ZNS2_4getTIS4_EERT_vEEspclsr3stdE7forwardIT_Efp_EEEDpOSA_", "decltype(-[DeploymentSetupController handleManualServerEntry:]::$_5& Ncr::Silver::Utility::detail::getT<-[DeploymentSetupController handleManualServerEntry:]::$_5>()()(std::forward<-[DeploymentSetupController handleManualServerEntry:]::$_5>(fp)...)) Ncr::Silver::Utility::detail::CallOnThread<-[DeploymentSetupController handleManualServerEntry:]::$_5>::operator()<>(-[DeploymentSetupController handleManualServerEntry:]::$_5&&...) const"},
{"_Zli2_xy", "operator\"\" _x(unsigned long long)"},
{"_Z1fIiEDcT_", "decltype(auto) f<int>(int)"},
{"_ZZ4testvEN1g3fooE5Point", "test()::g::foo(Point)"},
@@ -29604,13 +29604,19 @@
{"PFvRmOE", "void (*)(unsigned long&) &&"},
{"_ZTW1x", "thread-local wrapper routine for x"},
{"_ZTHN3fooE", "thread-local initialization routine for foo"},
- {"_Z4algoIJiiiEEvZ1gEUlT_E_", "void algo<int, int, int>(g::'lambda'(int, int, int))"},
+ {"_Z4algoIJiiiEEvZ1gEUlDpT_E_", "void algo<int, int, int>(g::'lambda'(int, int, int))"},
// attribute abi_tag
{"_Z1fB3foov", "f[abi:foo]()"},
{"_Z1fB3fooB3barv", "f[abi:foo][abi:bar]()"},
{"_ZN1SB5outer1fB5innerEv", "S[abi:outer]::f[abi:inner]()"},
{"_ZN1SC2B8ctor_tagEv", "S::S[abi:ctor_tag]()"},
{"_ZplB4MERP1SS_", "operator+[abi:MERP](S, S)"},
+
+ {"_Z1fIJifcEEvDp5unaryIT_E", "void f<int, float, char>(unary<int>, unary<float>, unary<char>)"},
+ {"_Z1fIJEJiEEvDpT_DpT0_", "void f<int>(int)"},
+ {"_Z1fIJicEEvDp7MuncherIAstT__S1_E", "void f<int, char>(Muncher<int [sizeof (int)]>, Muncher<char [sizeof (char)]>)"},
+ {"_ZN1SIJifcEE1fIJdjEEEiDp4MerpIJifcT_EE", "int S<int, float, char>::f<double, unsigned int>(Merp<int, float, char, double>, Merp<int, float, char, unsigned int>)"},
+ {"_Z1pIJicEEiDp4MerpIXsZT_EJT_EE", "int p<int, char>(Merp<sizeof...(int, char), int>, Merp<sizeof...(int, char), char>)"},
};
const unsigned N = sizeof(cases) / sizeof(cases[0]);
Index: src/cxa_demangle.cpp
===================================================================
--- src/cxa_demangle.cpp
+++ src/cxa_demangle.cpp
@@ -10,16 +10,17 @@
// FIXME: (possibly) incomplete list of features that clang mangles that this
// file does not yet support:
// - enable_if attribute
-// - decomposition declarations
// - C++ modules TS
+// - All C++14 and C++17 features
#define _LIBCPP_NO_EXCEPTIONS
#include "__cxxabi_config.h"
#include <vector>
#include <algorithm>
#include <numeric>
+#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
@@ -32,20 +33,7 @@
#endif
#endif
-namespace __cxxabiv1
-{
-
-namespace
-{
-
-enum
-{
- unknown_error = -4,
- invalid_args = -3,
- invalid_mangled_name,
- memory_alloc_failure,
- success
-};
+namespace {
class StringView {
const char *First;
@@ -82,6 +70,7 @@
const char *begin() const { return First; }
const char *end() const { return Last; }
size_t size() const { return static_cast<size_t>(Last - First); }
+ bool empty() const { return First == Last; }
};
bool operator==(const StringView &LHS, const StringView &RHS) {
@@ -110,6 +99,12 @@
OutputStream(char *StartBuf, size_t Size)
: Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
+ /// If a ParameterPackExpansion (or similar type) is encountered, the offset
+ /// into the pack that we're currently printing.
+ unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
+
+ bool PrintingFailed = false;
+
OutputStream &operator+=(StringView R) {
size_t Size = R.size();
if (Size == 0)
@@ -126,41 +121,7 @@
return *this;
}
- // Offset of position in buffer, used for building stream_string_view.
- typedef unsigned StreamPosition;
-
- // StringView into a stream, used for caching the ast nodes.
- class StreamStringView {
- StreamPosition First, Last;
-
- friend class OutputStream;
-
- public:
- StreamStringView() : First(0), Last(0) {}
-
- StreamStringView(StreamPosition First_, StreamPosition Last_)
- : First(First_), Last(Last_) {}
-
- bool empty() const { return First == Last; }
- };
-
- OutputStream &operator+=(StreamStringView &s) {
- size_t Sz = static_cast<size_t>(s.Last - s.First);
- if (Sz == 0)
- return *this;
- grow(Sz);
- memmove(Buffer + CurrentPosition, Buffer + s.First, Sz);
- CurrentPosition += Sz;
- return *this;
- }
-
- StreamPosition getCurrentPosition() const {
- return static_cast<StreamPosition>(CurrentPosition);
- }
-
- StreamStringView makeStringViewFromPastPosition(StreamPosition Pos) {
- return StreamStringView(Pos, getCurrentPosition());
- }
+ size_t getCurrentPosition() const { return CurrentPosition; };
char back() const {
return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
@@ -173,6 +134,21 @@
size_t getBufferCapacity() { return BufferCapacity; }
};
+template <class T>
+class SwapAndRestore {
+ T &Restore;
+ T OriginalValue;
+public:
+ SwapAndRestore(T& Restore_, T NewVal)
+ : Restore(Restore_), OriginalValue(Restore) {
+ Restore = std::move(NewVal);
+ }
+ ~SwapAndRestore() { Restore = std::move(OriginalValue); }
+
+ SwapAndRestore(const SwapAndRestore &) = delete;
+ SwapAndRestore &operator=(const SwapAndRestore &) = delete;
+};
+
// Base class of all AST nodes. The AST is built by the parser, then is
// traversed by the printLeft/Right functions to produce a demangled string.
class Node {
@@ -192,16 +168,19 @@
KPointerToMemberType,
KArrayType,
KFunctionType,
- KTopLevelFunctionDecl,
+ KFunctionEncoding,
KFunctionQualType,
KFunctionRefQualType,
KLiteralOperator,
KSpecialName,
KCtorVtableSpecialName,
KQualifiedName,
KEmptyName,
KVectorType,
- KTemplateParams,
+ KParameterPack,
+ KTemplateArgumentPack,
+ KParameterPackExpansion,
+ KTemplateArgs,
KNameWithTemplateArgs,
KGlobalQualifiedName,
KStdQualifiedName,
@@ -214,28 +193,71 @@
KExpr,
};
- const Kind K;
+ static constexpr unsigned NoParameterPack =
+ std::numeric_limits<unsigned>::max();
+ unsigned ParameterPackSize = NoParameterPack;
-private:
- // If this Node has any RHS part, potentally many Nodes further down.
- const unsigned HasRHSComponent : 1;
- const unsigned HasFunction : 1;
- const unsigned HasArray : 1;
+ Kind K;
-public:
- Node(Kind K_, bool HasRHS_ = false, bool HasFunction_ = false,
- bool HasArray_ = false)
- : K(K_), HasRHSComponent(HasRHS_), HasFunction(HasFunction_),
- HasArray(HasArray_) {}
+ /// Three-way bool to track a cached value. Unknown is possible if this node
+ /// has an unexpanded parameter pack below it that may affect this cache.
+ enum class Cache : unsigned char { Yes, No, Unknown, };
+
+ /// Tracks if this node has a component on its right side, in which case we
+ /// need to call printRight.
+ Cache RHSComponentCache;
+
+ /// Track if this node is a (possibly qualified) array type. This can affect
+ /// how we format the output string.
+ Cache ArrayCache;
+
+ /// Track if this node is a (possibly qualified) function type. This can
+ /// affect how we format the output string.
+ Cache FunctionCache;
- bool hasRHSComponent() const { return HasRHSComponent; }
- bool hasArray() const { return HasArray; }
- bool hasFunction() const { return HasFunction; }
+ Node(Kind K_, unsigned ParameterPackSize_ = NoParameterPack,
+ Cache RHSComponentCache_ = Cache::No, Cache ArrayCache_ = Cache::No,
+ Cache FunctionCache_ = Cache::No)
+ : ParameterPackSize(ParameterPackSize_), K(K_),
+ RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_),
+ FunctionCache(FunctionCache_) {}
- void print(OutputStream &s) const {
- printLeft(s);
- if (hasRHSComponent())
- printRight(s);
+ bool containsUnexpandedParameterPack() const {
+ return ParameterPackSize != NoParameterPack;
+ }
+
+ bool hasRHSComponent(OutputStream &S) const {
+ if (RHSComponentCache != Cache::Unknown)
+ return RHSComponentCache == Cache::Yes;
+ return hasRHSComponentSlow(S);
+ }
+
+ bool hasArray(OutputStream &S) const {
+ if (ArrayCache != Cache::Unknown)
+ return ArrayCache == Cache::Yes;
+ return hasArraySlow(S);
+ }
+
+ bool hasFunction(OutputStream &S) const {
+ if (FunctionCache != Cache::Unknown)
+ return FunctionCache == Cache::Yes;
+ return hasFunctionSlow(S);
+ }
+
+ Kind getKind() const { return K; }
+
+ virtual bool hasRHSComponentSlow(OutputStream &) const { return false; }
+ virtual bool hasArraySlow(OutputStream &) const { return false; }
+ virtual bool hasFunctionSlow(OutputStream &) const { return false; }
+
+ /// If this node is a pack expansion that expands to 0 elements. This can have
+ /// an effect on how we should format the output.
+ bool isEmptyPackExpansion() const;
+
+ void print(OutputStream &S) const {
+ printLeft(S);
+ if (RHSComponentCache != Cache::No)
+ printRight(S);
}
// Print the "left" side of this Node into OutputStream.
@@ -251,24 +273,47 @@
// Silence compiler warnings, this dtor will never be called.
virtual ~Node() = default;
+
+#if 0
+ void dump() const {
+ char *Buffer = static_cast<char*>(std::malloc(1024));
+ OutputStream S(Buffer, 1024);
+ print(S);
+ S += '\0';
+ if (S.PrintingFailed)
+ printf("Failed to print %p\n", (const void*)this);
+ else
+ printf("Symbol dump for %p: %s\n", (const void*)this, S.getBuffer());
+ std::free(S.getBuffer());
+ }
+#endif
};
class NodeArray {
Node **Elements;
size_t NumElements;
public:
- NodeArray() : NumElements(0) {}
+ NodeArray() : Elements(nullptr), NumElements(0) {}
NodeArray(Node **Elements_, size_t NumElements_)
: Elements(Elements_), NumElements(NumElements_) {}
bool empty() const { return NumElements == 0; }
size_t size() const { return NumElements; }
- void printWithSeperator(OutputStream &S, StringView Seperator) const {
+ Node **begin() const { return Elements; }
+ Node **end() const { return Elements + NumElements; }
+
+ Node *operator[](size_t Idx) const { return Elements[Idx]; }
+
+ void printWithComma(OutputStream &S) const {
+ bool FirstElement = true;
for (size_t Idx = 0; Idx != NumElements; ++Idx) {
- if (Idx)
- S += Seperator;
+ if (Elements[Idx]->isEmptyPackExpansion())
+ continue;
+ if (!FirstElement)
+ S += ", ";
+ FirstElement = false;
Elements[Idx]->print(S);
}
}
@@ -291,20 +336,22 @@
};
class VendorExtQualType final : public Node {
- const Node *Ext;
const Node *Ty;
+ const Node *Ext;
public:
- VendorExtQualType(Node *Ext_, Node *Ty_)
- : Node(KVendorExtQualType), Ext(Ext_), Ty(Ty_) {}
+ VendorExtQualType(Node *Ty_, Node *Ext_)
+ : Node(KVendorExtQualType,
+ std::min(Ty_->ParameterPackSize, Ext_->ParameterPackSize)),
+ Ty(Ty_), Ext(Ext_) {}
+
+ const Node* getQual() const { return Ext; }
void printLeft(OutputStream &S) const override {
- Ext->print(S);
+ Ty->print(S);
S += " ";
- Ty->printLeft(S);
+ Ext->print(S);
}
-
- void printRight(OutputStream &S) const override { Ty->printRight(S); }
};
enum Qualifiers {
@@ -334,14 +381,19 @@
public:
QualType(Node *Child_, Qualifiers Quals_)
- : Node(KQualType, Child_->hasRHSComponent(), Child_->hasFunction(),
- Child_->hasArray()),
+ : Node(KQualType, Child_->ParameterPackSize, Child_->RHSComponentCache,
+ Child_->ArrayCache, Child_->FunctionCache),
Quals(Quals_), Child(Child_) {}
- QualType(Node::Kind ChildKind_, Node *Child_, Qualifiers Quals_)
- : Node(ChildKind_, Child_->hasRHSComponent(), Child_->hasFunction(),
- Child_->hasArray()),
- Quals(Quals_), Child(Child_) {}
+ bool hasRHSComponentSlow(OutputStream &S) const override {
+ return Child->hasRHSComponent(S);
+ }
+ bool hasArraySlow(OutputStream &S) const override {
+ return Child->hasArray(S);
+ }
+ bool hasFunctionSlow(OutputStream &S) const override {
+ return Child->hasFunction(S);
+ }
void printLeft(OutputStream &S) const override {
Child->printLeft(S);
@@ -355,7 +407,8 @@
const Node *Ty;
public:
- ConversionOperatorType(Node *Ty_) : Node(KConversionOperatorType), Ty(Ty_) {}
+ ConversionOperatorType(Node *Ty_)
+ : Node(KConversionOperatorType, Ty_->ParameterPackSize), Ty(Ty_) {}
void printLeft(OutputStream &S) const override {
S += "operator ";
@@ -369,14 +422,13 @@
public:
PostfixQualifiedType(Node *Ty_, StringView Postfix_)
- : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
+ : Node(KPostfixQualifiedType, Ty_->ParameterPackSize),
+ Ty(Ty_), Postfix(Postfix_) {}
void printLeft(OutputStream &s) const override {
Ty->printLeft(s);
s += Postfix;
}
-
- void printRight(OutputStream &S) const override { Ty->printRight(S); }
};
class NameType final : public Node {
@@ -396,7 +448,9 @@
StringView Tag;
public:
AbiTagAttr(const Node* Base_, StringView Tag_)
- : Node(KAbiTagAttr), Base(Base_), Tag(Tag_) {}
+ : Node(KAbiTagAttr, Base_->ParameterPackSize, Base_->RHSComponentCache,
+ Base_->ArrayCache, Base_->FunctionCache),
+ Base(Base_), Tag(Tag_) {}
void printLeft(OutputStream &S) const override {
Base->printLeft(S);
@@ -417,14 +471,14 @@
: Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
bool isObjCObject() const {
- return Ty->K == KNameType &&
+ return Ty->getKind() == KNameType &&
static_cast<NameType *>(Ty)->getName() == "objc_object";
}
void printLeft(OutputStream &S) const override {
- Ty->printLeft(S);
+ Ty->print(S);
S += "<";
- Protocol->printLeft(S);
+ Protocol->print(S);
S += ">";
}
};
@@ -434,16 +488,22 @@
public:
PointerType(Node *Pointee_)
- : Node(KPointerType, Pointee_->hasRHSComponent()), Pointee(Pointee_) {}
+ : Node(KPointerType, Pointee_->ParameterPackSize,
+ Pointee_->RHSComponentCache),
+ Pointee(Pointee_) {}
+
+ bool hasRHSComponentSlow(OutputStream &S) const override {
+ return Pointee->hasRHSComponent(S);
+ }
void printLeft(OutputStream &s) const override {
// We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
- if (Pointee->K != KObjCProtoName ||
+ if (Pointee->getKind() != KObjCProtoName ||
!static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
Pointee->printLeft(s);
- if (Pointee->hasArray())
+ if (Pointee->hasArray(s))
s += " ";
- if (Pointee->hasArray() || Pointee->hasFunction())
+ if (Pointee->hasArray(s) || Pointee->hasFunction(s))
s += "(";
s += "*";
} else {
@@ -455,9 +515,9 @@
}
void printRight(OutputStream &s) const override {
- if (Pointee->K != KObjCProtoName ||
+ if (Pointee->getKind() != KObjCProtoName ||
!static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
- if (Pointee->hasArray() || Pointee->hasFunction())
+ if (Pointee->hasArray(s) || Pointee->hasFunction(s))
s += ")";
Pointee->printRight(s);
}
@@ -469,20 +529,25 @@
public:
LValueReferenceType(Node *Pointee_)
- : Node(KLValueReferenceType, Pointee_->hasRHSComponent()),
+ : Node(KLValueReferenceType, Pointee_->ParameterPackSize,
+ Pointee_->RHSComponentCache),
Pointee(Pointee_) {}
+ bool hasRHSComponentSlow(OutputStream &S) const override {
+ return Pointee->hasRHSComponent(S);
+ }
+
void printLeft(OutputStream &s) const override {
Pointee->printLeft(s);
- if (Pointee->hasArray())
+ if (Pointee->hasArray(s))
s += " ";
- if (Pointee->hasArray() || Pointee->hasFunction())
+ if (Pointee->hasArray(s) || Pointee->hasFunction(s))
s += "(&";
else
s += "&";
}
void printRight(OutputStream &s) const override {
- if (Pointee->hasArray() || Pointee->hasFunction())
+ if (Pointee->hasArray(s) || Pointee->hasFunction(s))
s += ")";
Pointee->printRight(s);
}
@@ -493,21 +558,26 @@
public:
RValueReferenceType(Node *Pointee_)
- : Node(KRValueReferenceType, Pointee_->hasRHSComponent()),
+ : Node(KRValueReferenceType, Pointee_->ParameterPackSize,
+ Pointee_->RHSComponentCache),
Pointee(Pointee_) {}
+ bool hasRHSComponentSlow(OutputStream &S) const override {
+ return Pointee->hasRHSComponent(S);
+ }
+
void printLeft(OutputStream &s) const override {
Pointee->printLeft(s);
- if (Pointee->hasArray())
+ if (Pointee->hasArray(s))
s += " ";
- if (Pointee->hasArray() || Pointee->hasFunction())
+ if (Pointee->hasArray(s) || Pointee->hasFunction(s))
s += "(&&";
else
s += "&&";
}
void printRight(OutputStream &s) const override {
- if (Pointee->hasArray() || Pointee->hasFunction())
+ if (Pointee->hasArray(s) || Pointee->hasFunction(s))
s += ")";
Pointee->printRight(s);
}
@@ -519,21 +589,28 @@
public:
PointerToMemberType(Node *ClassType_, Node *MemberType_)
- : Node(KPointerToMemberType, MemberType_->hasRHSComponent()),
+ : Node(KPointerToMemberType,
+ std::min(MemberType_->ParameterPackSize,
+ ClassType_->ParameterPackSize),
+ MemberType_->RHSComponentCache),
ClassType(ClassType_), MemberType(MemberType_) {}
+ bool hasRHSComponentSlow(OutputStream &S) const override {
+ return MemberType->hasRHSComponent(S);
+ }
+
void printLeft(OutputStream &s) const override {
MemberType->printLeft(s);
- if (MemberType->hasArray() || MemberType->hasFunction())
+ if (MemberType->hasArray(s) || MemberType->hasFunction(s))
s += "(";
else
s += " ";
ClassType->print(s);
s += "::*";
}
void printRight(OutputStream &s) const override {
- if (MemberType->hasArray() || MemberType->hasFunction())
+ if (MemberType->hasArray(s) || MemberType->hasFunction(s))
s += ")";
MemberType->printRight(s);
}
@@ -581,10 +658,24 @@
public:
ArrayType(Node *Base_, NodeOrString Dimension_)
- : Node(KArrayType, true, false, true), Base(Base_), Dimension(Dimension_) {}
+ : Node(KArrayType, Base_->ParameterPackSize,
+ /*RHSComponentCache=*/Cache::Yes,
+ /*ArrayCache=*/Cache::Yes),
+ Base(Base_), Dimension(Dimension_) {
+ if (Dimension.isNode())
+ ParameterPackSize =
+ std::min(ParameterPackSize, Dimension.asNode()->ParameterPackSize);
+ }
// Incomplete array type.
- ArrayType(Node *Base_) : Node(KArrayType, true, false, true), Base(Base_) {}
+ ArrayType(Node *Base_)
+ : Node(KArrayType, Base_->ParameterPackSize,
+ /*RHSComponentCache=*/Cache::Yes,
+ /*ArrayCache=*/Cache::Yes),
+ Base(Base_) {}
+
+ bool hasRHSComponentSlow(OutputStream &) const override { return true; }
+ bool hasArraySlow(OutputStream &) const override { return true; }
void printLeft(OutputStream &S) const override { Base->printLeft(S); }
@@ -607,7 +698,16 @@
public:
FunctionType(Node *Ret_, NodeArray Params_)
- : Node(KFunctionType, true, true), Ret(Ret_), Params(Params_) {}
+ : Node(KFunctionType, Ret_->ParameterPackSize,
+ /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
+ /*FunctionCache=*/Cache::Yes),
+ Ret(Ret_), Params(Params_) {
+ for (Node *P : Params)
+ ParameterPackSize = std::min(ParameterPackSize, P->ParameterPackSize);
+ }
+
+ bool hasRHSComponentSlow(OutputStream &) const override { return true; }
+ bool hasFunctionSlow(OutputStream &) const override { return true; }
// Handle C++'s ... quirky decl grammer by using the left & right
// distinction. Consider:
@@ -623,34 +723,46 @@
void printRight(OutputStream &S) const override {
S += "(";
- Params.printWithSeperator(S, ", ");
+ Params.printWithComma(S);
S += ")";
Ret->printRight(S);
}
};
-class TopLevelFunctionDecl final : public Node {
+class FunctionEncoding final : public Node {
const Node *Ret;
const Node *Name;
NodeArray Params;
public:
- TopLevelFunctionDecl(Node *Ret_, Node *Name_, NodeArray Params_)
- : Node(KTopLevelFunctionDecl, true, true), Ret(Ret_), Name(Name_),
- Params(Params_) {}
+ FunctionEncoding(Node *Ret_, Node *Name_, NodeArray Params_)
+ : Node(KFunctionEncoding, NoParameterPack,
+ /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
+ /*FunctionCache=*/Cache::Yes),
+ Ret(Ret_), Name(Name_), Params(Params_) {
+ for (Node *P : Params)
+ ParameterPackSize = std::min(ParameterPackSize, P->ParameterPackSize);
+ if (Ret)
+ ParameterPackSize = std::min(ParameterPackSize, Ret->ParameterPackSize);
+ }
+
+ bool hasRHSComponentSlow(OutputStream &) const override { return true; }
+ bool hasFunctionSlow(OutputStream &) const override { return true; }
+
+ Node *getName() { return const_cast<Node *>(Name); }
void printLeft(OutputStream &S) const override {
if (Ret) {
Ret->printLeft(S);
- if (!Ret->hasRHSComponent())
+ if (!Ret->hasRHSComponent(S))
S += " ";
}
Name->print(S);
}
void printRight(OutputStream &S) const override {
S += "(";
- Params.printWithSeperator(S, ", ");
+ Params.printWithComma(S);
S += ")";
if (Ret)
Ret->printRight(S);
@@ -671,7 +783,13 @@
public:
FunctionRefQualType(Node *Fn_, FunctionRefQual Quals_)
- : Node(KFunctionRefQualType, true, true), Fn(Fn_), Quals(Quals_) {}
+ : Node(KFunctionRefQualType, Fn_->ParameterPackSize,
+ /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
+ /*FunctionCache=*/Cache::Yes),
+ Fn(Fn_), Quals(Quals_) {}
+
+ bool hasFunctionSlow(OutputStream &) const override { return true; }
+ bool hasRHSComponentSlow(OutputStream &) const override { return true; }
void printQuals(OutputStream &S) const {
if (Quals == FrefQualLValue)
@@ -691,12 +809,14 @@
class FunctionQualType final : public QualType {
public:
FunctionQualType(Node *Child_, Qualifiers Quals_)
- : QualType(KFunctionQualType, Child_, Quals_) {}
+ : QualType(Child_, Quals_) {
+ K = KFunctionQualType;
+ }
void printLeft(OutputStream &S) const override { Child->printLeft(S); }
void printRight(OutputStream &S) const override {
- if (Child->K == KFunctionRefQualType) {
+ if (Child->getKind() == KFunctionRefQualType) {
auto *RefQuals = static_cast<const FunctionRefQualType *>(Child);
RefQuals->Fn->printRight(S);
printQuals(S);
@@ -712,7 +832,8 @@
const Node *OpName;
public:
- LiteralOperator(Node *OpName_) : Node(KLiteralOperator), OpName(OpName_) {}
+ LiteralOperator(Node *OpName_)
+ : Node(KLiteralOperator, OpName_->ParameterPackSize), OpName(OpName_) {}
void printLeft(OutputStream &S) const override {
S += "operator\"\" ";
@@ -725,8 +846,9 @@
const Node *Child;
public:
- SpecialName(StringView Special_, Node *Child_)
- : Node(KSpecialName), Special(Special_), Child(Child_) {}
+ SpecialName(StringView Special_, Node* Child_)
+ : Node(KSpecialName, Child_->ParameterPackSize), Special(Special_),
+ Child(Child_) {}
void printLeft(OutputStream &S) const override {
S += Special;
@@ -740,8 +862,9 @@
public:
CtorVtableSpecialName(Node *FirstType_, Node *SecondType_)
- : Node(KCtorVtableSpecialName), FirstType(FirstType_),
- SecondType(SecondType_) {}
+ : Node(KCtorVtableSpecialName, std::min(FirstType_->ParameterPackSize,
+ SecondType_->ParameterPackSize)),
+ FirstType(FirstType_), SecondType(SecondType_) {}
void printLeft(OutputStream &S) const override {
S += "construction vtable for ";
@@ -756,27 +879,18 @@
const Node *Qualifier;
const Node *Name;
- mutable OutputStream::StreamStringView Cache;
-
public:
- QualifiedName(Node *Qualifier_, Node *Name_)
- : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
+ QualifiedName(Node* Qualifier_, Node* Name_)
+ : Node(KQualifiedName,
+ std::min(Qualifier_->ParameterPackSize, Name_->ParameterPackSize)),
+ Qualifier(Qualifier_), Name(Name_) {}
StringView getBaseName() const override { return Name->getBaseName(); }
void printLeft(OutputStream &S) const override {
- if (!Cache.empty()) {
- S += Cache;
- return;
- }
-
- OutputStream::StreamPosition Start = S.getCurrentPosition();
- if (Qualifier->K != KEmptyName) {
- Qualifier->print(S);
- S += "::";
- }
+ Qualifier->print(S);
+ S += "::";
Name->print(S);
- Cache = S.makeStringViewFromPastPosition(Start);
}
};
@@ -794,10 +908,17 @@
public:
VectorType(NodeOrString Dimension_)
: Node(KVectorType), BaseType(nullptr), Dimension(Dimension_),
- IsPixel(true) {}
+ IsPixel(true) {
+ if (Dimension.isNode())
+ ParameterPackSize = Dimension.asNode()->ParameterPackSize;
+ }
VectorType(Node *BaseType_, NodeOrString Dimension_)
- : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_),
- IsPixel(false) {}
+ : Node(KVectorType, BaseType_->ParameterPackSize), BaseType(BaseType_),
+ Dimension(Dimension_), IsPixel(false) {
+ if (Dimension.isNode())
+ ParameterPackSize =
+ std::min(ParameterPackSize, Dimension.asNode()->ParameterPackSize);
+ }
void printLeft(OutputStream &S) const override {
if (IsPixel) {
@@ -816,29 +937,159 @@
}
};
-class TemplateParams final : public Node {
- NodeArray Params;
+/// An unexpanded parameter pack (either in the expression or type context). If
+/// this AST is correct, this node will have a ParameterPackExpansion node above
+/// it.
+///
+/// This node is created when some <template-args> are found that apply to an
+/// <encoding>, and is stored in the TemplateParams table. In order for this to
+/// appear in the final AST, it has to referenced via a <template-param> (ie,
+/// T_).
+class ParameterPack final : public Node {
+ NodeArray Data;
+public:
+ ParameterPack(NodeArray Data_)
+ : Node(KParameterPack, static_cast<unsigned>(Data_.size())), Data(Data_) {
+ ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;
+ if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
+ return P->ArrayCache == Cache::No;
+ }))
+ ArrayCache = Cache::No;
+ if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
+ return P->FunctionCache == Cache::No;
+ }))
+ FunctionCache = Cache::No;
+ if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
+ return P->RHSComponentCache == Cache::No;
+ }))
+ RHSComponentCache = Cache::No;
+ }
- mutable OutputStream::StreamStringView Cache;
+ bool hasRHSComponentSlow(OutputStream &S) const override {
+ size_t Idx = S.CurrentPackIndex;
+ return Idx < Data.size() && Data[Idx]->hasRHSComponent(S);
+ }
+ bool hasArraySlow(OutputStream &S) const override {
+ size_t Idx = S.CurrentPackIndex;
+ return Idx < Data.size() && Data[Idx]->hasArray(S);
+ }
+ bool hasFunctionSlow(OutputStream &S) const override {
+ size_t Idx = S.CurrentPackIndex;
+ return Idx < Data.size() && Data[Idx]->hasFunction(S);
+ }
+ void printLeft(OutputStream &S) const override {
+ size_t Idx = S.CurrentPackIndex;
+ // If this index is out of range, or UINT_MAX (in which case we're not even
+ // expanding a pack) then this is an invalid mangled name.
+ if (Idx >= Data.size()) {
+ S.PrintingFailed = true;
+ return;
+ }
+ Data[Idx]->printLeft(S);
+ }
+ void printRight(OutputStream &S) const override {
+ size_t Idx = S.CurrentPackIndex;
+ // If this index is out of range, or UINT_MAX (in which case we're not even
+ // expanding a pack) then this is an invalid mangled name.
+ if (Idx >= Data.size()) {
+ S.PrintingFailed = true;
+ return;
+ }
+ Data[Idx]->printRight(S);
+ }
+};
+
+/// A variadic template argument. This node represents an occurance of
+/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
+/// one of it's Elements is. The parser inserts a ParameterPack into the
+/// TemplateParams table if the <template-args> this pack belongs to apply to an
+/// <encoding>.
+class TemplateArgumentPack final : public Node {
+ NodeArray Elements;
public:
- TemplateParams(NodeArray Params_) : Node(KTemplateParams), Params(Params_) {}
+ TemplateArgumentPack(NodeArray Elements_)
+ : Node(KTemplateArgumentPack), Elements(Elements_) {
+ for (Node *E : Elements)
+ ParameterPackSize = std::min(E->ParameterPackSize, ParameterPackSize);
+ }
+
+ NodeArray getElements() const { return Elements; }
void printLeft(OutputStream &S) const override {
- if (!Cache.empty()) {
- S += Cache;
+ Elements.printWithComma(S);
+ }
+};
+
+/// A pack expansion. Below this node, there are some unexpanded ParameterPacks
+/// which each have Child->ParameterPackSize elements.
+class ParameterPackExpansion final : public Node {
+ const Node *Child;
+
+public:
+ ParameterPackExpansion(Node* Child_)
+ : Node(KParameterPackExpansion), Child(Child_) {}
+
+ const Node *getChild() const { return Child; }
+
+ void printLeft(OutputStream &S) const override {
+ unsigned PackSize = Child->ParameterPackSize;
+ if (PackSize == NoParameterPack) {
+ Child->print(S);
+ S += "...";
return;
}
- OutputStream::StreamPosition Start = S.getCurrentPosition();
+ SwapAndRestore<unsigned> SavePackIndex(S.CurrentPackIndex, 0);
+ for (unsigned I = 0; I != PackSize; ++I) {
+ if (I != 0)
+ S += ", ";
+ S.CurrentPackIndex = I;
+ Child->print(S);
+ }
+ }
+};
+
+inline bool Node::isEmptyPackExpansion() const {
+ if (getKind() == KParameterPackExpansion) {
+ auto *AsPack = static_cast<const ParameterPackExpansion *>(this);
+ return AsPack->getChild()->isEmptyPackExpansion();
+ }
+ if (getKind() == KTemplateArgumentPack) {
+ auto *AsTemplateArg = static_cast<const TemplateArgumentPack *>(this);
+ for (Node *E : AsTemplateArg->getElements())
+ if (!E->isEmptyPackExpansion())
+ return false;
+ return true;
+ }
+ return ParameterPackSize == 0;
+}
+
+class TemplateArgs final : public Node {
+ NodeArray Params;
+
+public:
+ TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {
+ for (Node *P : Params)
+ ParameterPackSize = std::min(ParameterPackSize, P->ParameterPackSize);
+ }
+
+ NodeArray getParams() { return Params; }
+ void printLeft(OutputStream &S) const override {
S += "<";
- Params.printWithSeperator(S, ", ");
+ bool FirstElement = true;
+ for (size_t Idx = 0, E = Params.size(); Idx != E; ++Idx) {
+ if (Params[Idx]->isEmptyPackExpansion())
+ continue;
+ if (!FirstElement)
+ S += ", ";
+ FirstElement = false;
+ Params[Idx]->print(S);
+ }
if (S.back() == '>')
S += " ";
S += ">";
-
- Cache = S.makeStringViewFromPastPosition(Start);
}
};
@@ -849,7 +1100,9 @@
public:
NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
- : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
+ : Node(KNameWithTemplateArgs, std::min(Name_->ParameterPackSize,
+ TemplateArgs_->ParameterPackSize)),
+ Name(Name_), TemplateArgs(TemplateArgs_) {}
StringView getBaseName() const override { return Name->getBaseName(); }
@@ -863,7 +1116,8 @@
Node *Child;
public:
- GlobalQualifiedName(Node *Child_) : Node(KGlobalQualifiedName), Child(Child_) {}
+ GlobalQualifiedName(Node* Child_)
+ : Node(KGlobalQualifiedName, Child_->ParameterPackSize), Child(Child_) {}
StringView getBaseName() const override { return Child->getBaseName(); }
@@ -877,7 +1131,8 @@
Node *Child;
public:
- StdQualifiedName(Node *Child_) : Node(KStdQualifiedName), Child(Child_) {}
+ StdQualifiedName(Node *Child_)
+ : Node(KStdQualifiedName, Child_->ParameterPackSize), Child(Child_) {}
StringView getBaseName() const override { return Child->getBaseName(); }
@@ -1000,7 +1255,8 @@
public:
CtorDtorName(Node *Basename_, bool IsDtor_)
- : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_) {}
+ : Node(KCtorDtorName, Basename_->ParameterPackSize),
+ Basename(Basename_), IsDtor(IsDtor_) {}
void printLeft(OutputStream &S) const override {
if (IsDtor)
@@ -1013,7 +1269,9 @@
const Node *Base;
public:
- DtorName(Node *Base_) : Node(KDtorName), Base(Base_) {}
+ DtorName(Node *Base_) : Node(KDtorName), Base(Base_) {
+ ParameterPackSize = Base->ParameterPackSize;
+ }
void printLeft(OutputStream &S) const override {
S += "~";
@@ -1040,13 +1298,16 @@
public:
LambdaTypeName(NodeArray Params_, StringView Count_)
- : Node(KLambdaTypeName), Params(Params_), Count(Count_) {}
+ : Node(KLambdaTypeName), Params(Params_), Count(Count_) {
+ for (Node *P : Params)
+ ParameterPackSize = std::min(ParameterPackSize, P->ParameterPackSize);
+ }
void printLeft(OutputStream &S) const override {
S += "\'lambda";
S += Count;
S += "\'(";
- Params.printWithSeperator(S, ", ");
+ Params.printWithComma(S);
S += ")";
}
};
@@ -1064,7 +1325,10 @@
public:
BinaryExpr(Node *LHS_, StringView InfixOperator_, Node *RHS_)
- : LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {}
+ : LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {
+ ParameterPackSize =
+ std::min(LHS->ParameterPackSize, RHS->ParameterPackSize);
+ }
void printLeft(OutputStream &S) const override {
// might be a template argument expression, then we need to disambiguate
@@ -1090,7 +1354,10 @@
const Node *Op2;
public:
- ArraySubscriptExpr(Node *Op1_, Node *Op2_) : Op1(Op1_), Op2(Op2_) {}
+ ArraySubscriptExpr(Node *Op1_, Node *Op2_) : Op1(Op1_), Op2(Op2_) {
+ ParameterPackSize =
+ std::min(Op1->ParameterPackSize, Op2->ParameterPackSize);
+ }
void printLeft(OutputStream &S) const override {
S += "(";
@@ -1107,7 +1374,9 @@
public:
PostfixExpr(Node *Child_, StringView Operand_)
- : Child(Child_), Operand(Operand_) {}
+ : Child(Child_), Operand(Operand_) {
+ ParameterPackSize = Child->ParameterPackSize;
+ }
void printLeft(OutputStream &S) const override {
S += "(";
@@ -1124,7 +1393,11 @@
public:
ConditionalExpr(Node *Cond_, Node *Then_, Node *Else_)
- : Cond(Cond_), Then(Then_), Else(Else_) {}
+ : Cond(Cond_), Then(Then_), Else(Else_) {
+ ParameterPackSize =
+ std::min(Cond->ParameterPackSize,
+ std::min(Then->ParameterPackSize, Else->ParameterPackSize));
+ }
void printLeft(OutputStream &S) const override {
S += "(";
@@ -1144,7 +1417,10 @@
public:
MemberExpr(Node *LHS_, StringView Kind_, Node *RHS_)
- : LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
+ : LHS(LHS_), Kind(Kind_), RHS(RHS_) {
+ ParameterPackSize =
+ std::min(LHS->ParameterPackSize, RHS->ParameterPackSize);
+ }
void printLeft(OutputStream &S) const override {
LHS->print(S);
@@ -1160,7 +1436,9 @@
public:
EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_)
- : Prefix(Prefix_), Infix(Infix_), Postfix(Postfix_) {}
+ : Prefix(Prefix_), Infix(Infix_), Postfix(Postfix_) {
+ ParameterPackSize = Infix->ParameterPackSize;
+ }
void printLeft(OutputStream &S) const override {
S += Prefix;
@@ -1177,7 +1455,10 @@
public:
CastExpr(StringView CastKind_, Node *To_, Node *From_)
- : CastKind(CastKind_), To(To_), From(From_) {}
+ : CastKind(CastKind_), To(To_), From(From_) {
+ ParameterPackSize =
+ std::min(To->ParameterPackSize, From->ParameterPackSize);
+ }
void printLeft(OutputStream &S) const override {
S += CastKind;
@@ -1190,14 +1471,15 @@
};
class SizeofParamPackExpr : public Expr {
- NodeArray Args;
+ Node *Pack;
public:
- SizeofParamPackExpr(NodeArray Args_) : Args(Args_) {}
+ SizeofParamPackExpr(Node *Pack_) : Pack(Pack_) {}
void printLeft(OutputStream &S) const override {
S += "sizeof...(";
- Args.printWithSeperator(S, ", ");
+ ParameterPackExpansion PPE(Pack);
+ PPE.printLeft(S);
S += ")";
}
};
@@ -1207,12 +1489,16 @@
NodeArray Args;
public:
- CallExpr(Node *Callee_, NodeArray Args_) : Callee(Callee_), Args(Args_) {}
+ CallExpr(Node *Callee_, NodeArray Args_) : Callee(Callee_), Args(Args_) {
+ for (Node *P : Args)
+ ParameterPackSize = std::min(ParameterPackSize, P->ParameterPackSize);
+ ParameterPackSize = std::min(ParameterPackSize, Callee->ParameterPackSize);
+ }
void printLeft(OutputStream &S) const override {
Callee->print(S);
S += "(";
- Args.printWithSeperator(S, ", ");
+ Args.printWithComma(S);
S += ")";
}
};
@@ -1227,8 +1513,15 @@
public:
NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
bool IsArray_)
- : ExprList(ExprList_), Type(Type_), InitList(InitList_), IsGlobal(IsGlobal_),
- IsArray(IsArray_) {}
+ : ExprList(ExprList_), Type(Type_), InitList(InitList_),
+ IsGlobal(IsGlobal_), IsArray(IsArray_) {
+ for (Node *E : ExprList)
+ ParameterPackSize = std::min(ParameterPackSize, E->ParameterPackSize);
+ for (Node *I : InitList)
+ ParameterPackSize = std::min(ParameterPackSize, I->ParameterPackSize);
+ if (Type)
+ ParameterPackSize = std::min(ParameterPackSize, Type->ParameterPackSize);
+ }
void printLeft(OutputStream &S) const override {
if (IsGlobal)
@@ -1238,15 +1531,16 @@
S += "[]";
if (!ExprList.empty()) {
S += "(";
- ExprList.printWithSeperator(S, ", ");
+ ExprList.printWithComma(S);
S += ")";
}
Type->print(S);
if (!InitList.empty()) {
S += "(";
- InitList.printWithSeperator(S, ", ");
+ InitList.printWithComma(S);
S += ")";
}
+
}
};
@@ -1257,7 +1551,9 @@
public:
DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_)
- : Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
+ : Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {
+ ParameterPackSize = Op->ParameterPackSize;
+ }
void printLeft(OutputStream &S) const override {
if (IsGlobal)
@@ -1274,7 +1570,9 @@
Node *Child;
public:
- PrefixExpr(StringView Prefix_, Node *Child_) : Prefix(Prefix_), Child(Child_) {}
+ PrefixExpr(StringView Prefix_, Node *Child_) : Prefix(Prefix_), Child(Child_) {
+ ParameterPackSize = Child->ParameterPackSize;
+ }
void printLeft(OutputStream &S) const override {
S += Prefix;
@@ -1296,41 +1594,34 @@
}
};
-class ExprList : public Expr {
- NodeArray SubExprs;
-
-public:
- ExprList(NodeArray SubExprs_) : SubExprs(SubExprs_) {}
-
- void printLeft(OutputStream &S) const override {
- S += "(";
- SubExprs.printWithSeperator(S, ", ");
- S += ")";
- }
-};
-
class ConversionExpr : public Expr {
+ const Node *Type;
NodeArray Expressions;
- NodeArray Types;
public:
- ConversionExpr(NodeArray Expressions_, NodeArray Types_)
- : Expressions(Expressions_), Types(Types_) {}
+ ConversionExpr(const Node *Type_, NodeArray Expressions_)
+ : Type(Type_), Expressions(Expressions_) {
+ for (Node *E : Expressions)
+ ParameterPackSize = std::min(ParameterPackSize, E->ParameterPackSize);
+ ParameterPackSize = std::min(ParameterPackSize, Type->ParameterPackSize);
+ }
void printLeft(OutputStream &S) const override {
S += "(";
- Expressions.printWithSeperator(S, ", ");
+ Type->print(S);
S += ")(";
- Types.printWithSeperator(S, ", ");
+ Expressions.printWithComma(S);
S += ")";
}
};
class ThrowExpr : public Expr {
const Node *Op;
public:
- ThrowExpr(Node *Op_) : Op(Op_) {}
+ ThrowExpr(Node *Op_) : Op(Op_) {
+ ParameterPackSize = Op->ParameterPackSize;
+ }
void printLeft(OutputStream &S) const override {
S += "throw ";
@@ -1355,7 +1646,9 @@
StringView Integer;
public:
- IntegerCastExpr(Node *Ty_, StringView Integer_) : Ty(Ty_), Integer(Integer_) {}
+ IntegerCastExpr(Node *Ty_, StringView Integer_) : Ty(Ty_), Integer(Integer_) {
+ ParameterPackSize = Ty->ParameterPackSize;
+ }
void printLeft(OutputStream &S) const override {
S += "(";
@@ -1593,94 +1886,22 @@
}
};
-// Substitution table. This type is used to track the substitutions that are
-// known by the parser.
-template <size_t Size>
-class SubstitutionTable {
- // Substitutions hold the actual entries in the table, and PackIndices tells
- // us which entries are members of which pack. For example, if the
- // substitutions we're tracking are: {int, {float, FooBar}, char}, with
- // {float, FooBar} being a parameter pack, we represent the substitutions as:
- // Substitutions: int, float, FooBar, char
- // PackIndices: 0, 1, 3
- // So, PackIndicies[I] holds the offset of the begin of the Ith pack, and
- // PackIndices[I + 1] holds the offset of the end.
- PODSmallVector<Node*, Size> Substitutions;
- PODSmallVector<unsigned, Size> PackIndices;
-
-public:
- // Add a substitution that represents a single name to the table. This is
- // modeled as a parameter pack with just one element.
- void pushSubstitution(Node* Entry) {
- pushPack();
- pushSubstitutionIntoPack(Entry);
- }
-
- // Add a new empty pack to the table. Subsequent calls to
- // pushSubstitutionIntoPack() will add to this pack.
- void pushPack() {
- PackIndices.push_back(static_cast<unsigned>(Substitutions.size()));
- }
- void pushSubstitutionIntoPack(Node* Entry) {
- assert(!PackIndices.empty() && "No pack to push substitution into!");
- Substitutions.push_back(Entry);
- }
-
- // Remove the last pack from the table.
- void popPack() {
- unsigned Last = PackIndices.back();
- PackIndices.pop_back();
- Substitutions.dropBack(Last);
- }
-
- // For use in a range-for loop.
- struct NodeRange {
- Node** First;
- Node** Last;
- Node** begin() { return First; }
- Node** end() { return Last; }
- };
-
- // Retrieve the Nth substitution. This is represented as a range, as the
- // substitution could be referring to a parameter pack.
- NodeRange nthSubstitution(size_t N) {
- assert(PackIndices[N] <= Substitutions.size());
- // The Nth parameter pack starts at offset PackIndices[N], and ends at
- // PackIndices[N + 1].
- Node** Begin = Substitutions.begin() + PackIndices[N];
- Node** End;
- if (N + 1 != PackIndices.size()) {
- assert(PackIndices[N + 1] <= Substitutions.size());
- End = Substitutions.begin() + PackIndices[N + 1];
- } else
- End = Substitutions.end();
- assert(Begin <= End);
- return NodeRange{Begin, End};
- }
-
- size_t size() const { return PackIndices.size(); }
- bool empty() const { return PackIndices.empty(); }
- void clear() {
- Substitutions.clear();
- PackIndices.clear();
- }
-};
-
struct Db
{
// Name stack, this is used by the parser to hold temporary names that were
// parsed. The parser colapses multiple names into new nodes to construct
// the AST. Once the parser is finished, names.size() == 1.
PODSmallVector<Node*, 32> Names;
// Substitution table. Itanium supports name substitutions as a means of
- // compression. The string "S42_" refers to the 42nd entry in this table.
- SubstitutionTable<32> Subs;
+ // compression. The string "S42_" refers to the 44nd entry (base-36) in this
+ // table.
+ PODSmallVector<Node*, 32> Subs;
// Template parameter table. Like the above, but referenced like "T42_".
// This has a smaller size compared to Subs and Names because it can be
// stored on the stack.
- SubstitutionTable<4> TemplateParams;
+ PODSmallVector<Node *, 8> TemplateParams;
Qualifiers CV = QualNone;
FunctionRefQual RefQuals = FrefQualNone;
@@ -1938,8 +2159,7 @@
case '_':
if (!db.Subs.empty())
{
- for (Node* n : db.Subs.nthSubstitution(0))
- db.Names.push_back(n);
+ db.Names.push_back(db.Subs[0]);
first += 2;
}
break;
@@ -1965,8 +2185,7 @@
++sub;
if (sub < db.Subs.size())
{
- for (Node* n : db.Subs.nthSubstitution(sub))
- db.Names.push_back(n);
+ db.Names.push_back(db.Subs[sub]);
first = t+1;
}
}
@@ -2197,8 +2416,7 @@
{
if (!db.TemplateParams.empty())
{
- for (Node *t : db.TemplateParams.nthSubstitution(0))
- db.Names.push_back(t);
+ db.Names.push_back(db.TemplateParams[0]);
first += 2;
}
else
@@ -2222,8 +2440,7 @@
++sub;
if (sub < db.TemplateParams.size())
{
- for (Node *temp : db.TemplateParams.nthSubstitution(sub))
- db.Names.push_back(temp);
+ db.Names.push_back(db.TemplateParams[sub]);
first = t+1;
}
else
@@ -2356,9 +2573,13 @@
{
if (last - first >= 3 && first[0] == 's' && first[1] == 'p')
{
+ size_t before = db.Names.size();
const char* t = parse_expression(first+2, last, db);
+ if (before + 1 != db.Names.size())
+ return first;
if (t != first+2)
first = t;
+ db.Names.back() = db.make<ParameterPackExpansion>(db.Names.back());
}
return first;
}
@@ -2413,11 +2634,9 @@
size_t k0 = db.Names.size();
const char* t = parse_template_param(first+2, last, db);
size_t k1 = db.Names.size();
- if (t != first+2 && k0 <= k1)
+ if (t != first+2 && k0 + 1 == k1)
{
- Node* sizeof_expr = db.make<SizeofParamPackExpr>(
- db.popTrailingNodeArray(k0));
- db.Names.push_back(sizeof_expr);
+ db.Names.back() = db.make<SizeofParamPackExpr>(db.Names.back());
first = t;
}
}
@@ -2604,7 +2823,7 @@
size_t k1 = db.Names.size();
if (t != first && k1 == k0 + 1)
{
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
first = t;
}
else
@@ -2620,7 +2839,7 @@
{
if (db.Names.empty())
return first;
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
first = t;
}
break;
@@ -2639,7 +2858,7 @@
return first;
db.Names.back() =
db.make<StdQualifiedName>(db.Names.back());
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
first = t;
}
}
@@ -3054,7 +3273,7 @@
{
bool TryToParseTemplateArgs = db.TryToParseTemplateArgs;
db.TryToParseTemplateArgs = false;
- size_t type_begin = db.Names.size();
+ size_t type_index = db.Names.size();
const char* t = parse_type(first+2, last, db);
db.TryToParseTemplateArgs = TryToParseTemplateArgs;
if (t != first+2 && t != last)
@@ -3085,16 +3304,13 @@
++t;
}
if (db.Names.size() < expr_list_begin ||
- type_begin > expr_list_begin)
+ type_index + 1 != expr_list_begin)
return first;
NodeArray expressions = db.makeNodeArray(
db.Names.begin() + (long)expr_list_begin, db.Names.end());
- NodeArray types = db.makeNodeArray(
- db.Names.begin() + (long)type_begin,
- db.Names.begin() + (long)expr_list_begin);
auto* conv_expr = db.make<ConversionExpr>(
- types, expressions);
- db.Names.dropBack(type_begin);
+ db.Names[type_index], expressions);
+ db.Names.dropBack(type_index);
db.Names.push_back(conv_expr);
first = t;
}
@@ -3444,23 +3660,20 @@
size_t k0 = db.Names.size();
const char* t1 = parse_type(t, last, db);
size_t k1 = db.Names.size();
- if (t1 != t)
+ if (t1 != t && k0 + 1 == k1)
{
if (is_function)
- db.Subs.popPack();
- db.Subs.pushPack();
- for (size_t k = k0; k < k1; ++k)
+ db.Subs.pop_back();
+ if (cv)
{
- if (cv) {
- if (is_function)
- db.Names[k] = db.make<FunctionQualType>(
- db.Names[k], cv);
- else
- db.Names[k] =
- db.make<QualType>(db.Names[k], cv);
- }
- db.Subs.pushSubstitutionIntoPack(db.Names[k]);
+ if (is_function)
+ db.Names.back() = db.make<FunctionQualType>(
+ db.Names.back(), cv);
+ else
+ db.Names.back() =
+ db.make<QualType>(db.Names.back(), cv);
}
+ db.Subs.push_back(db.Names.back());
first = t1;
}
}
@@ -3484,7 +3697,7 @@
if (db.Names.empty())
return first;
first = t;
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
}
break;
case 'C':
@@ -3496,7 +3709,7 @@
db.Names.back() = db.make<PostfixQualifiedType>(
db.Names.back(), " complex");
first = t;
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
}
break;
case 'F':
@@ -3506,7 +3719,7 @@
if (db.Names.empty())
return first;
first = t;
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
}
break;
case 'G':
@@ -3518,7 +3731,7 @@
db.Names.back() = db.make<PostfixQualifiedType>(
db.Names.back(), " imaginary");
first = t;
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
}
break;
case 'M':
@@ -3528,23 +3741,19 @@
if (db.Names.empty())
return first;
first = t;
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
}
break;
case 'O':
{
size_t k0 = db.Names.size();
t = parse_type(first+1, last, db);
size_t k1 = db.Names.size();
- if (t != first+1)
+ if (t != first+1 || k0 + 1 == k1)
{
- db.Subs.pushPack();
- for (size_t k = k0; k < k1; ++k)
- {
- db.Names[k] =
- db.make<RValueReferenceType>(db.Names[k]);
- db.Subs.pushSubstitutionIntoPack(db.Names[k]);
- }
+ db.Names.back() =
+ db.make<RValueReferenceType>(db.Names.back());
+ db.Subs.push_back(db.Names.back());
first = t;
}
break;
@@ -3554,14 +3763,10 @@
size_t k0 = db.Names.size();
t = parse_type(first+1, last, db);
size_t k1 = db.Names.size();
- if (t != first+1)
+ if (t != first+1 && k0 + 1 == k1)
{
- db.Subs.pushPack();
- for (size_t k = k0; k < k1; ++k)
- {
- db.Names[k] = db.make<PointerType>(db.Names[k]);
- db.Subs.pushSubstitutionIntoPack(db.Names[k]);
- }
+ db.Names.back() = db.make<PointerType>(db.Names.back());
+ db.Subs.push_back(db.Names.back());
first = t;
}
break;
@@ -3571,15 +3776,11 @@
size_t k0 = db.Names.size();
t = parse_type(first+1, last, db);
size_t k1 = db.Names.size();
- if (t != first+1)
+ if (t != first+1 && k0 + 1 == k1)
{
- db.Subs.pushPack();
- for (size_t k = k0; k < k1; ++k)
- {
- db.Names[k] =
- db.make<LValueReferenceType>(db.Names[k]);
- db.Subs.pushSubstitutionIntoPack(db.Names[k]);
- }
+ db.Names.back() =
+ db.make<LValueReferenceType>(db.Names.back());
+ db.Subs.push_back(db.Names.back());
first = t;
}
break;
@@ -3589,11 +3790,9 @@
size_t k0 = db.Names.size();
t = parse_template_param(first, last, db);
size_t k1 = db.Names.size();
- if (t != first)
+ if (t != first && k0 + 1 == k1)
{
- db.Subs.pushPack();
- for (size_t k = k0; k < k1; ++k)
- db.Subs.pushSubstitutionIntoPack(db.Names[k]);
+ db.Subs.push_back(db.Names.back());
if (db.TryToParseTemplateArgs && k1 == k0+1)
{
const char* t1 = parse_template_args(t, last, db);
@@ -3604,7 +3803,7 @@
db.Names.back() = db.make<
NameWithTemplateArgs>(
db.Names.back(), args);
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
t = t1;
}
}
@@ -3644,7 +3843,7 @@
db.Names.push_back(db.make<VendorExtQualType>(type, proto));
}
}
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
first = t2;
}
}
@@ -3658,7 +3857,7 @@
{
if (db.Names.empty())
return first;
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
first = t;
}
}
@@ -3683,7 +3882,7 @@
NameWithTemplateArgs>(
db.Names.back(), template_args);
// Need to create substitution for <template-template-param> <template-args>
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
first = t;
}
}
@@ -3700,11 +3899,12 @@
size_t k0 = db.Names.size();
t = parse_type(first+2, last, db);
size_t k1 = db.Names.size();
- if (t != first+2)
+ if (t != first+2 && k0 + 1 == k1)
{
- db.Subs.pushPack();
- for (size_t k = k0; k < k1; ++k)
- db.Subs.pushSubstitutionIntoPack(db.Names[k]);
+ db.Names.back() =
+ db.make<ParameterPackExpansion>(
+ db.Names.back());
+ db.Subs.push_back(db.Names.back());
first = t;
return first;
}
@@ -3717,7 +3917,7 @@
{
if (db.Names.empty())
return first;
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
first = t;
return first;
}
@@ -3728,7 +3928,7 @@
{
if (db.Names.empty())
return first;
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
first = t;
return first;
}
@@ -3751,7 +3951,7 @@
{
if (db.Names.empty())
return first;
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
first = t;
}
}
@@ -5199,7 +5399,6 @@
// ::= <expr-primary> # simple expressions
// ::= J <template-arg>* E # argument pack
// ::= LZ <encoding> E # extension
-
const char*
parse_template_arg(const char* first, const char* last, Db& db)
{
@@ -5216,19 +5415,23 @@
first = t+1;
}
break;
- case 'J':
+ case 'J': {
t = first+1;
if (t == last)
return first;
+ size_t ArgsBegin = db.Names.size();
while (*t != 'E')
{
const char* t1 = parse_template_arg(t, last, db);
if (t1 == t)
return first;
t = t1;
}
+ NodeArray Args = db.popTrailingNodeArray(ArgsBegin);
+ db.Names.push_back(db.make<TemplateArgumentPack>(Args));
first = t+1;
break;
+ }
case 'L':
// <expr-primary> or LZ <encoding> E
if (first+1 != last && first[1] == 'Z')
@@ -5251,7 +5454,6 @@
// <template-args> ::= I <template-arg>* E
// extension, the abi says <template-arg>+
-
const char*
parse_template_args(const char* first, const char* last, Db& db)
{
@@ -5270,12 +5472,14 @@
const char* t1 = parse_template_arg(t, last, db);
size_t k1 = db.Names.size();
db.TemplateParams = std::move(TmpParams);
-
- if (t1 == t || t1 == last || k0 > k1)
+ if (t1 == t || t1 == last || k0 + 1 != k1)
return first;
- db.TemplateParams.pushPack();
- for (size_t k = k0; k < k1; ++k)
- db.TemplateParams.pushSubstitutionIntoPack(db.Names[k]);
+ Node *TableEntry = db.Names.back();
+ if (TableEntry->getKind() == Node::KTemplateArgumentPack)
+ TableEntry = db.make<ParameterPack>(
+ static_cast<TemplateArgumentPack*>(TableEntry)
+ ->getElements());
+ db.TemplateParams.push_back(TableEntry);
t = t1;
continue;
}
@@ -5289,7 +5493,7 @@
if (begin_idx > db.Names.size())
return first;
first = t + 1;
- TemplateParams* tp = db.make<TemplateParams>(
+ auto *tp = db.make<TemplateArgs>(
db.popTrailingNodeArray(begin_idx));
db.Names.push_back(tp);
}
@@ -5363,7 +5567,7 @@
{
db.Names.back() = db.make<QualifiedName>(
db.Names.back(), name);
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
}
else
db.Names.back() = name;
@@ -5386,7 +5590,7 @@
db.make<QualifiedName>(db.Names.back(), name);
else
db.Names.back() = name;
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
pop_subs = true;
t0 = t1;
}
@@ -5408,7 +5612,7 @@
db.make<QualifiedName>(db.Names.back(), name);
else
db.Names.back() = name;
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
pop_subs = true;
t0 = t1;
}
@@ -5425,7 +5629,7 @@
db.Names.pop_back();
db.Names.back() = db.make<NameWithTemplateArgs>(
db.Names.back(), name);
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
t0 = t1;
component_ends_with_template_args = true;
}
@@ -5450,7 +5654,7 @@
db.make<QualifiedName>(db.Names.back(), name);
else
db.Names.back() = name;
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
pop_subs = true;
t0 = t1;
}
@@ -5461,7 +5665,7 @@
first = t0 + 1;
db.CV = cv;
if (pop_subs && !db.Subs.empty())
- db.Subs.popPack();
+ db.Subs.pop_back();
if (ends_with_template_args)
*ends_with_template_args = component_ends_with_template_args;
}
@@ -5626,7 +5830,7 @@
{
if (db.Names.empty())
return first;
- db.Subs.pushSubstitution(db.Names.back());
+ db.Subs.push_back(db.Names.back());
t0 = t1;
t1 = parse_template_args(t0, last, db);
if (t1 != t0)
@@ -6013,7 +6217,7 @@
return first;
Node* name = db.Names.back();
db.Names.pop_back();
- result = db.make<TopLevelFunctionDecl>(
+ result = db.make<FunctionEncoding>(
return_type, name, NodeArray());
}
else
@@ -6034,7 +6238,7 @@
return first;
Node* name = db.Names.back();
db.Names.pop_back();
- result = db.make<TopLevelFunctionDecl>(
+ result = db.make<FunctionEncoding>(
return_type, name, params);
}
if (ref != FrefQualNone)
@@ -6111,12 +6315,19 @@
return first;
}
+enum {
+ unknown_error = -4,
+ invalid_args = -3,
+ invalid_mangled_name,
+ memory_alloc_failure,
+ success
+};
+
// <block-involcaton-function> ___Z<encoding>_block_invoke
// <block-involcaton-function> ___Z<encoding>_block_invoke<decimal-digit>+
// <block-involcaton-function> ___Z<encoding>_block_invoke_<decimal-digit>+
// <mangled-name> ::= _Z<encoding>
// ::= <type>
-
void
demangle(const char* first, const char* last, Db& db, int& status)
{
@@ -6167,6 +6378,8 @@
} // unnamed namespace
+
+namespace __cxxabiv1 {
extern "C" _LIBCXXABI_FUNC_VIS char *
__cxa_demangle(const char *mangled_name, char *buf, size_t *n, int *status) {
if (mangled_name == nullptr || (buf != nullptr && n == nullptr))
@@ -6195,6 +6408,10 @@
internal_status = invalid_mangled_name;
}
+ if (internal_status == success &&
+ db.Names.back()->containsUnexpandedParameterPack())
+ internal_status = invalid_mangled_name;
+
if (internal_status == success)
{
if (!buf)
@@ -6210,6 +6427,10 @@
s += '\0';
if (n) *n = s.getCurrentPosition();
buf = s.getBuffer();
+ if (s.PrintingFailed) {
+ internal_status = invalid_mangled_name;
+ buf = nullptr;
+ }
}
else
internal_status = memory_alloc_failure;
@@ -6220,5 +6441,4 @@
*status = internal_status;
return buf;
}
-
} // __cxxabiv1
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits