}
};
-template <typename Alloc>
-struct Db {
+template <typename Derived, typename Alloc> struct AbstractManglingParser {
const char *First;
const char *Last;
Alloc ASTAllocator;
- Db(const char *First_, const char *Last_) : First(First_), Last(Last_) {}
+ AbstractManglingParser(const char *First_, const char *Last_)
+ : First(First_), Last(Last_) {}
+
+ Derived &getDerived() { return static_cast<Derived &>(*this); }
void reset(const char *First_, const char *Last_) {
First = First_;
FunctionRefQual ReferenceQualifier = FrefQualNone;
size_t ForwardTemplateRefsBegin;
- NameState(Db *Enclosing)
+ NameState(AbstractManglingParser *Enclosing)
: ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
};
//
// <unscoped-template-name> ::= <unscoped-name>
// ::= <substitution>
-template<typename Alloc> Node *Db<Alloc>::parseName(NameState *State) {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
consumeIf('L'); // extension
if (look() == 'N')
- return parseNestedName(State);
+ return getDerived().parseNestedName(State);
if (look() == 'Z')
- return parseLocalName(State);
+ return getDerived().parseLocalName(State);
// ::= <unscoped-template-name> <template-args>
if (look() == 'S' && look(1) != 't') {
- Node *S = parseSubstitution();
+ Node *S = getDerived().parseSubstitution();
if (S == nullptr)
return nullptr;
if (look() != 'I')
return nullptr;
- Node *TA = parseTemplateArgs(State != nullptr);
+ Node *TA = getDerived().parseTemplateArgs(State != nullptr);
if (TA == nullptr)
return nullptr;
if (State) State->EndsWithTemplateArgs = true;
return make<NameWithTemplateArgs>(S, TA);
}
- Node *N = parseUnscopedName(State);
+ Node *N = getDerived().parseUnscopedName(State);
if (N == nullptr)
return nullptr;
// ::= <unscoped-template-name> <template-args>
if (look() == 'I') {
Subs.push_back(N);
- Node *TA = parseTemplateArgs(State != nullptr);
+ Node *TA = getDerived().parseTemplateArgs(State != nullptr);
if (TA == nullptr)
return nullptr;
if (State) State->EndsWithTemplateArgs = true;
// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
// := Z <function encoding> E s [<discriminator>]
// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
-template<typename Alloc> Node *Db<Alloc>::parseLocalName(NameState *State) {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
if (!consumeIf('Z'))
return nullptr;
- Node *Encoding = parseEncoding();
+ Node *Encoding = getDerived().parseEncoding();
if (Encoding == nullptr || !consumeIf('E'))
return nullptr;
parseNumber(true);
if (!consumeIf('_'))
return nullptr;
- Node *N = parseName(State);
+ Node *N = getDerived().parseName(State);
if (N == nullptr)
return nullptr;
return make<LocalName>(Encoding, N);
}
- Node *Entity = parseName(State);
+ Node *Entity = getDerived().parseName(State);
if (Entity == nullptr)
return nullptr;
First = parse_discriminator(First, Last);
// <unscoped-name> ::= <unqualified-name>
// ::= St <unqualified-name> # ::std::
// extension ::= StL<unqualified-name>
-template<typename Alloc> Node *Db<Alloc>::parseUnscopedName(NameState *State) {
- if (consumeIf("StL") || consumeIf("St")) {
- Node *R = parseUnqualifiedName(State);
- if (R == nullptr)
- return nullptr;
- return make<StdQualifiedName>(R);
- }
- return parseUnqualifiedName(State);
+template <typename Derived, typename Alloc>
+Node *
+AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State) {
+ if (consumeIf("StL") || consumeIf("St")) {
+ Node *R = getDerived().parseUnqualifiedName(State);
+ if (R == nullptr)
+ return nullptr;
+ return make<StdQualifiedName>(R);
+ }
+ return getDerived().parseUnqualifiedName(State);
}
// <unqualified-name> ::= <operator-name> [abi-tags]
// ::= <source-name>
// ::= <unnamed-type-name>
// ::= DC <source-name>+ E # structured binding declaration
-template<typename Alloc>
-Node *Db<Alloc>::parseUnqualifiedName(NameState *State) {
+template <typename Derived, typename Alloc>
+Node *
+AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(NameState *State) {
// <ctor-dtor-name>s are special-cased in parseNestedName().
Node *Result;
if (look() == 'U')
- Result = parseUnnamedTypeName(State);
+ Result = getDerived().parseUnnamedTypeName(State);
else if (look() >= '1' && look() <= '9')
- Result = parseSourceName(State);
+ Result = getDerived().parseSourceName(State);
else if (consumeIf("DC")) {
size_t BindingsBegin = Names.size();
do {
- Node *Binding = parseSourceName(State);
+ Node *Binding = getDerived().parseSourceName(State);
if (Binding == nullptr)
return nullptr;
Names.push_back(Binding);
} while (!consumeIf('E'));
Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
} else
- Result = parseOperatorName(State);
+ Result = getDerived().parseOperatorName(State);
if (Result != nullptr)
- Result = parseAbiTags(Result);
+ Result = getDerived().parseAbiTags(Result);
return Result;
}
// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
//
// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
-template<typename Alloc> Node *Db<Alloc>::parseUnnamedTypeName(NameState *) {
+template <typename Derived, typename Alloc>
+Node *
+AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *) {
if (consumeIf("Ut")) {
StringView Count = parseNumber();
if (!consumeIf('_'))
if (!consumeIf("vE")) {
size_t ParamsBegin = Names.size();
do {
- Node *P = parseType();
+ Node *P = getDerived().parseType();
if (P == nullptr)
return nullptr;
Names.push_back(P);
}
// <source-name> ::= <positive length number> <identifier>
-template<typename Alloc> Node *Db<Alloc>::parseSourceName(NameState *) {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
size_t Length = 0;
if (parsePositiveInteger(&Length))
return nullptr;
// ::= rS # >>=
// ::= ss # <=> C++2a
// ::= v <digit> <source-name> # vendor extended operator
-template<typename Alloc> Node *Db<Alloc>::parseOperatorName(NameState *State) {
+template <typename Derived, typename Alloc>
+Node *
+AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
switch (look()) {
case 'a':
switch (look(1)) {
SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
PermitForwardTemplateReferences ||
State != nullptr);
- Node* Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (Ty == nullptr)
return nullptr;
if (State) State->CtorDtorConversion = true;
// ::= li <source-name> # operator ""
case 'i': {
First += 2;
- Node *SN = parseSourceName(State);
+ Node *SN = getDerived().parseSourceName(State);
if (SN == nullptr)
return nullptr;
return make<LiteralOperator>(SN);
case 'v':
if (std::isdigit(look(1))) {
First += 2;
- Node *SN = parseSourceName(State);
+ Node *SN = getDerived().parseSourceName(State);
if (SN == nullptr)
return nullptr;
return make<ConversionOperatorType>(SN);
// ::= D1 # complete object destructor
// ::= D2 # base object destructor
// extension ::= D5 # ?
-template<typename Alloc>
-Node *Db<Alloc>::parseCtorDtorName(Node *&SoFar, NameState *State) {
+template <typename Derived, typename Alloc>
+Node *
+AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
+ NameState *State) {
if (SoFar->getKind() == Node::KSpecialSubstitution) {
auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
switch (SSK) {
++First;
if (State) State->CtorDtorConversion = true;
if (IsInherited) {
- if (parseName(State) == nullptr)
+ if (getDerived().parseName(State) == nullptr)
return nullptr;
}
return make<CtorDtorName>(SoFar, false, Variant);
// <template-prefix> ::= <prefix> <template unqualified-name>
// ::= <template-param>
// ::= <substitution>
-template<typename Alloc> Node *Db<Alloc>::parseNestedName(NameState *State) {
+template <typename Derived, typename Alloc>
+Node *
+AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
if (!consumeIf('N'))
return nullptr;
// ::= <template-param>
if (look() == 'T') {
- if (!PushComponent(parseTemplateParam()))
+ if (!PushComponent(getDerived().parseTemplateParam()))
return nullptr;
Subs.push_back(SoFar);
continue;
// ::= <template-prefix> <template-args>
if (look() == 'I') {
- Node *TA = parseTemplateArgs(State != nullptr);
+ Node *TA = getDerived().parseTemplateArgs(State != nullptr);
if (TA == nullptr || SoFar == nullptr)
return nullptr;
SoFar = make<NameWithTemplateArgs>(SoFar, TA);
// ::= <decltype>
if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
- if (!PushComponent(parseDecltype()))
+ if (!PushComponent(getDerived().parseDecltype()))
return nullptr;
Subs.push_back(SoFar);
continue;
// ::= <substitution>
if (look() == 'S' && look(1) != 't') {
- Node *S = parseSubstitution();
+ Node *S = getDerived().parseSubstitution();
if (!PushComponent(S))
return nullptr;
if (SoFar != S)
if (look() == 'C' || (look() == 'D' && look(1) != 'C')) {
if (SoFar == nullptr)
return nullptr;
- if (!PushComponent(parseCtorDtorName(SoFar, State)))
+ if (!PushComponent(getDerived().parseCtorDtorName(SoFar, State)))
return nullptr;
- SoFar = parseAbiTags(SoFar);
+ SoFar = getDerived().parseAbiTags(SoFar);
if (SoFar == nullptr)
return nullptr;
Subs.push_back(SoFar);
}
// ::= <prefix> <unqualified-name>
- if (!PushComponent(parseUnqualifiedName(State)))
+ if (!PushComponent(getDerived().parseUnqualifiedName(State)))
return nullptr;
Subs.push_back(SoFar);
}
}
// <simple-id> ::= <source-name> [ <template-args> ]
-template<typename Alloc> Node *Db<Alloc>::parseSimpleId() {
- Node *SN = parseSourceName(/*NameState=*/nullptr);
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
+ Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
if (SN == nullptr)
return nullptr;
if (look() == 'I') {
- Node *TA = parseTemplateArgs();
+ Node *TA = getDerived().parseTemplateArgs();
if (TA == nullptr)
return nullptr;
return make<NameWithTemplateArgs>(SN, TA);
// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
// ::= <simple-id> # e.g., ~A<2*N>
-template<typename Alloc> Node *Db<Alloc>::parseDestructorName() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Node *Result;
if (std::isdigit(look()))
- Result = parseSimpleId();
+ Result = getDerived().parseSimpleId();
else
- Result = parseUnresolvedType();
+ Result = getDerived().parseUnresolvedType();
if (Result == nullptr)
return nullptr;
return make<DtorName>(Result);
// <unresolved-type> ::= <template-param>
// ::= <decltype>
// ::= <substitution>
-template<typename Alloc> Node *Db<Alloc>::parseUnresolvedType() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
if (look() == 'T') {
- Node *TP = parseTemplateParam();
+ Node *TP = getDerived().parseTemplateParam();
if (TP == nullptr)
return nullptr;
Subs.push_back(TP);
return TP;
}
if (look() == 'D') {
- Node *DT = parseDecltype();
+ Node *DT = getDerived().parseDecltype();
if (DT == nullptr)
return nullptr;
Subs.push_back(DT);
return DT;
}
- return parseSubstitution();
+ return getDerived().parseSubstitution();
}
// <base-unresolved-name> ::= <simple-id> # unresolved name
// ::= on <operator-name> <template-args> # unresolved operator template-id
// ::= dn <destructor-name> # destructor or pseudo-destructor;
// # e.g. ~X or ~X<N-1>
-template<typename Alloc> Node *Db<Alloc>::parseBaseUnresolvedName() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
if (std::isdigit(look()))
- return parseSimpleId();
+ return getDerived().parseSimpleId();
if (consumeIf("dn"))
- return parseDestructorName();
+ return getDerived().parseDestructorName();
consumeIf("on");
- Node *Oper = parseOperatorName(/*NameState=*/nullptr);
+ Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
if (Oper == nullptr)
return nullptr;
if (look() == 'I') {
- Node *TA = parseTemplateArgs();
+ Node *TA = getDerived().parseTemplateArgs();
if (TA == nullptr)
return nullptr;
return make<NameWithTemplateArgs>(Oper, TA);
// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
//
// <unresolved-qualifier-level> ::= <simple-id>
-template<typename Alloc> Node *Db<Alloc>::parseUnresolvedName() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName() {
Node *SoFar = nullptr;
// srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
// srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
if (consumeIf("srN")) {
- SoFar = parseUnresolvedType();
+ SoFar = getDerived().parseUnresolvedType();
if (SoFar == nullptr)
return nullptr;
if (look() == 'I') {
- Node *TA = parseTemplateArgs();
+ Node *TA = getDerived().parseTemplateArgs();
if (TA == nullptr)
return nullptr;
SoFar = make<NameWithTemplateArgs>(SoFar, TA);
}
while (!consumeIf('E')) {
- Node *Qual = parseSimpleId();
+ Node *Qual = getDerived().parseSimpleId();
if (Qual == nullptr)
return nullptr;
SoFar = make<QualifiedName>(SoFar, Qual);
return nullptr;
}
- Node *Base = parseBaseUnresolvedName();
+ Node *Base = getDerived().parseBaseUnresolvedName();
if (Base == nullptr)
return nullptr;
return make<QualifiedName>(SoFar, Base);
// [gs] <base-unresolved-name> # x or (with "gs") ::x
if (!consumeIf("sr")) {
- SoFar = parseBaseUnresolvedName();
+ SoFar = getDerived().parseBaseUnresolvedName();
if (SoFar == nullptr)
return nullptr;
if (Global)
// [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
if (std::isdigit(look())) {
do {
- Node *Qual = parseSimpleId();
+ Node *Qual = getDerived().parseSimpleId();
if (Qual == nullptr)
return nullptr;
if (SoFar)
// sr <unresolved-type> <base-unresolved-name>
// sr <unresolved-type> <template-args> <base-unresolved-name>
else {
- SoFar = parseUnresolvedType();
+ SoFar = getDerived().parseUnresolvedType();
if (SoFar == nullptr)
return nullptr;
if (look() == 'I') {
- Node *TA = parseTemplateArgs();
+ Node *TA = getDerived().parseTemplateArgs();
if (TA == nullptr)
return nullptr;
SoFar = make<NameWithTemplateArgs>(SoFar, TA);
assert(SoFar != nullptr);
- Node *Base = parseBaseUnresolvedName();
+ Node *Base = getDerived().parseBaseUnresolvedName();
if (Base == nullptr)
return nullptr;
return make<QualifiedName>(SoFar, Base);
// <abi-tags> ::= <abi-tag> [<abi-tags>]
// <abi-tag> ::= B <source-name>
-template<typename Alloc> Node *Db<Alloc>::parseAbiTags(Node *N) {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
while (consumeIf('B')) {
StringView SN = parseBareSourceName();
if (SN.empty())
}
// <number> ::= [n] <non-negative decimal integer>
-template<typename Alloc>
-StringView Db<Alloc>::parseNumber(bool AllowNegative) {
+template <typename Alloc, typename Derived>
+StringView
+AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
const char *Tmp = First;
if (AllowNegative)
consumeIf('n');
}
// <positive length number> ::= [0-9]*
-template<typename Alloc> bool Db<Alloc>::parsePositiveInteger(size_t *Out) {
+template <typename Alloc, typename Derived>
+bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
*Out = 0;
if (look() < '0' || look() > '9')
return true;
return false;
}
-template<typename Alloc> StringView Db<Alloc>::parseBareSourceName() {
+template <typename Alloc, typename Derived>
+StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
size_t Int = 0;
if (parsePositiveInteger(&Int) || numLeft() < Int)
return StringView();
//
// <ref-qualifier> ::= R # & ref-qualifier
// <ref-qualifier> ::= O # && ref-qualifier
-template<typename Alloc> Node *Db<Alloc>::parseFunctionType() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Qualifiers CVQuals = parseCVQualifiers();
Node *ExceptionSpec = nullptr;
if (!ExceptionSpec)
return nullptr;
} else if (consumeIf("DO")) {
- Node *E = parseExpr();
+ Node *E = getDerived().parseExpr();
if (E == nullptr || !consumeIf('E'))
return nullptr;
ExceptionSpec = make<NoexceptSpec>(E);
} else if (consumeIf("Dw")) {
size_t SpecsBegin = Names.size();
while (!consumeIf('E')) {
- Node *T = parseType();
+ Node *T = getDerived().parseType();
if (T == nullptr)
return nullptr;
Names.push_back(T);
if (!consumeIf('F'))
return nullptr;
consumeIf('Y'); // extern "C"
- Node *ReturnType = parseType();
+ Node *ReturnType = getDerived().parseType();
if (ReturnType == nullptr)
return nullptr;
ReferenceQualifier = FrefQualRValue;
break;
}
- Node *T = parseType();
+ Node *T = getDerived().parseType();
if (T == nullptr)
return nullptr;
Names.push_back(T);
// ::= Dv [<dimension expression>] _ <element type>
// <extended element type> ::= <element type>
// ::= p # AltiVec vector pixel
-template<typename Alloc> Node *Db<Alloc>::parseVectorType() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
if (!consumeIf("Dv"))
return nullptr;
if (look() >= '1' && look() <= '9') {
return nullptr;
if (consumeIf('p'))
return make<PixelVectorType>(DimensionNumber);
- Node *ElemType = parseType();
+ Node *ElemType = getDerived().parseType();
if (ElemType == nullptr)
return nullptr;
return make<VectorType>(ElemType, DimensionNumber);
}
if (!consumeIf('_')) {
- Node *DimExpr = parseExpr();
+ Node *DimExpr = getDerived().parseExpr();
if (!DimExpr)
return nullptr;
if (!consumeIf('_'))
return nullptr;
- Node *ElemType = parseType();
+ Node *ElemType = getDerived().parseType();
if (!ElemType)
return nullptr;
return make<VectorType>(ElemType, DimExpr);
}
- Node *ElemType = parseType();
+ Node *ElemType = getDerived().parseType();
if (!ElemType)
return nullptr;
return make<VectorType>(ElemType, StringView());
// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
// ::= DT <expression> E # decltype of an expression (C++0x)
-template<typename Alloc> Node *Db<Alloc>::parseDecltype() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
if (!consumeIf('D'))
return nullptr;
if (!consumeIf('t') && !consumeIf('T'))
return nullptr;
- Node *E = parseExpr();
+ Node *E = getDerived().parseExpr();
if (E == nullptr)
return nullptr;
if (!consumeIf('E'))
// <array-type> ::= A <positive dimension number> _ <element type>
// ::= A [<dimension expression>] _ <element type>
-template<typename Alloc> Node *Db<Alloc>::parseArrayType() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
if (!consumeIf('A'))
return nullptr;
if (!consumeIf('_'))
return nullptr;
} else if (!consumeIf('_')) {
- Node *DimExpr = parseExpr();
+ Node *DimExpr = getDerived().parseExpr();
if (DimExpr == nullptr)
return nullptr;
if (!consumeIf('_'))
Dimension = DimExpr;
}
- Node *Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (Ty == nullptr)
return nullptr;
return make<ArrayType>(Ty, Dimension);
}
// <pointer-to-member-type> ::= M <class type> <member type>
-template<typename Alloc> Node *Db<Alloc>::parsePointerToMemberType() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
if (!consumeIf('M'))
return nullptr;
- Node *ClassType = parseType();
+ Node *ClassType = getDerived().parseType();
if (ClassType == nullptr)
return nullptr;
- Node *MemberType = parseType();
+ Node *MemberType = getDerived().parseType();
if (MemberType == nullptr)
return nullptr;
return make<PointerToMemberType>(ClassType, MemberType);
// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
// ::= Tu <name> # dependent elaborated type specifier using 'union'
// ::= Te <name> # dependent elaborated type specifier using 'enum'
-template<typename Alloc> Node *Db<Alloc>::parseClassEnumType() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
StringView ElabSpef;
if (consumeIf("Ts"))
ElabSpef = "struct";
else if (consumeIf("Te"))
ElabSpef = "enum";
- Node *Name = parseName();
+ Node *Name = getDerived().parseName();
if (Name == nullptr)
return nullptr;
// <qualified-type> ::= <qualifiers> <type>
// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
-template<typename Alloc> Node *Db<Alloc>::parseQualifiedType() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
if (consumeIf('U')) {
StringView Qual = parseBareSourceName();
if (Qual.empty())
}
if (Proto.empty())
return nullptr;
- Node *Child = parseQualifiedType();
+ Node *Child = getDerived().parseQualifiedType();
if (Child == nullptr)
return nullptr;
return make<ObjCProtoName>(Child, Proto);
}
- Node *Child = parseQualifiedType();
+ Node *Child = getDerived().parseQualifiedType();
if (Child == nullptr)
return nullptr;
return make<VendorExtQualType>(Child, Qual);
}
Qualifiers Quals = parseCVQualifiers();
- Node *Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (Ty == nullptr)
return nullptr;
if (Quals != QualNone)
//
// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
-template<typename Alloc> Node *Db<Alloc>::parseType() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Node *Result = nullptr;
if (TypeCallback != nullptr)
(look(AfterQuals) == 'D' &&
(look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
- Result = parseFunctionType();
+ Result = getDerived().parseFunctionType();
break;
}
LLVM_FALLTHROUGH;
}
case 'U': {
- Result = parseQualifiedType();
+ Result = getDerived().parseQualifiedType();
break;
}
// <builtin-type> ::= v # void
// ::= <decltype>
case 't':
case 'T': {
- Result = parseDecltype();
+ Result = getDerived().parseDecltype();
break;
}
// extension ::= <vector-type> # <vector-type> starts with Dv
case 'v': {
- Result = parseVectorType();
+ Result = getDerived().parseVectorType();
break;
}
// ::= Dp <type> # pack expansion (C++0x)
case 'p': {
First += 2;
- Node *Child = parseType();
+ Node *Child = getDerived().parseType();
if (!Child)
return nullptr;
Result = make<ParameterPackExpansion>(Child);
case 'w':
// Transaction safe function type.
case 'x':
- Result = parseFunctionType();
+ Result = getDerived().parseFunctionType();
break;
}
break;
// ::= <function-type>
case 'F': {
- Result = parseFunctionType();
+ Result = getDerived().parseFunctionType();
break;
}
// ::= <array-type>
case 'A': {
- Result = parseArrayType();
+ Result = getDerived().parseArrayType();
break;
}
// ::= <pointer-to-member-type>
case 'M': {
- Result = parsePointerToMemberType();
+ Result = getDerived().parsePointerToMemberType();
break;
}
// ::= <template-param>
case 'T': {
// This could be an elaborate type specifier on a <class-enum-type>.
if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
- Result = parseClassEnumType();
+ Result = getDerived().parseClassEnumType();
break;
}
- Result = parseTemplateParam();
+ Result = getDerived().parseTemplateParam();
if (Result == nullptr)
return nullptr;
// parse them, take the second production.
if (TryToParseTemplateArgs && look() == 'I') {
- Node *TA = parseTemplateArgs();
+ Node *TA = getDerived().parseTemplateArgs();
if (TA == nullptr)
return nullptr;
Result = make<NameWithTemplateArgs>(Result, TA);
// ::= P <type> # pointer
case 'P': {
++First;
- Node *Ptr = parseType();
+ Node *Ptr = getDerived().parseType();
if (Ptr == nullptr)
return nullptr;
Result = make<PointerType>(Ptr);
// ::= R <type> # l-value reference
case 'R': {
++First;
- Node *Ref = parseType();
+ Node *Ref = getDerived().parseType();
if (Ref == nullptr)
return nullptr;
Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
// ::= O <type> # r-value reference (C++11)
case 'O': {
++First;
- Node *Ref = parseType();
+ Node *Ref = getDerived().parseType();
if (Ref == nullptr)
return nullptr;
Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
// ::= C <type> # complex pair (C99)
case 'C': {
++First;
- Node *P = parseType();
+ Node *P = getDerived().parseType();
if (P == nullptr)
return nullptr;
Result = make<PostfixQualifiedType>(P, " complex");
// ::= G <type> # imaginary (C99)
case 'G': {
++First;
- Node *P = parseType();
+ Node *P = getDerived().parseType();
if (P == nullptr)
return P;
Result = make<PostfixQualifiedType>(P, " imaginary");
// ::= <substitution> # See Compression below
case 'S': {
if (look(1) && look(1) != 't') {
- Node *Sub = parseSubstitution();
+ Node *Sub = getDerived().parseSubstitution();
if (Sub == nullptr)
return nullptr;
// parse them, take the second production.
if (TryToParseTemplateArgs && look() == 'I') {
- Node *TA = parseTemplateArgs();
+ Node *TA = getDerived().parseTemplateArgs();
if (TA == nullptr)
return nullptr;
Result = make<NameWithTemplateArgs>(Sub, TA);
}
// ::= <class-enum-type>
default: {
- Result = parseClassEnumType();
+ Result = getDerived().parseClassEnumType();
break;
}
}
return Result;
}
-template<typename Alloc> Node *Db<Alloc>::parsePrefixExpr(StringView Kind) {
- Node *E = parseExpr();
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind) {
+ Node *E = getDerived().parseExpr();
if (E == nullptr)
return nullptr;
return make<PrefixExpr>(Kind, E);
}
-template<typename Alloc> Node *Db<Alloc>::parseBinaryExpr(StringView Kind) {
- Node *LHS = parseExpr();
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind) {
+ Node *LHS = getDerived().parseExpr();
if (LHS == nullptr)
return nullptr;
- Node *RHS = parseExpr();
+ Node *RHS = getDerived().parseExpr();
if (RHS == nullptr)
return nullptr;
return make<BinaryExpr>(LHS, Kind, RHS);
}
-template<typename Alloc> Node *Db<Alloc>::parseIntegerLiteral(StringView Lit) {
+template <typename Derived, typename Alloc>
+Node *
+AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
StringView Tmp = parseNumber(true);
if (!Tmp.empty() && consumeIf('E'))
return make<IntegerLiteral>(Lit, Tmp);
}
// <CV-Qualifiers> ::= [r] [V] [K]
-template<typename Alloc> Qualifiers Db<Alloc>::parseCVQualifiers() {
+template <typename Alloc, typename Derived>
+Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Qualifiers CVR = QualNone;
if (consumeIf('r'))
CVR |= QualRestrict;
// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
-template<typename Alloc> Node *Db<Alloc>::parseFunctionParam() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
if (consumeIf("fp")) {
parseCVQualifiers();
StringView Num = parseNumber();
// [gs] na <expression>* _ <type> E # new[] (expr-list) type
// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
// <initializer> ::= pi <expression>* E # parenthesized initialization
-template<typename Alloc> Node *Db<Alloc>::parseNewExpr() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseNewExpr() {
bool Global = consumeIf("gs");
bool IsArray = look(1) == 'a';
if (!consumeIf("nw") && !consumeIf("na"))
return nullptr;
size_t Exprs = Names.size();
while (!consumeIf('_')) {
- Node *Ex = parseExpr();
+ Node *Ex = getDerived().parseExpr();
if (Ex == nullptr)
return nullptr;
Names.push_back(Ex);
}
NodeArray ExprList = popTrailingNodeArray(Exprs);
- Node *Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (Ty == nullptr)
return Ty;
if (consumeIf("pi")) {
size_t InitsBegin = Names.size();
while (!consumeIf('E')) {
- Node *Init = parseExpr();
+ Node *Init = getDerived().parseExpr();
if (Init == nullptr)
return Init;
Names.push_back(Init);
// cv <type> <expression> # conversion with one argument
// cv <type> _ <expression>* E # conversion with a different number of arguments
-template<typename Alloc> Node *Db<Alloc>::parseConversionExpr() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
if (!consumeIf("cv"))
return nullptr;
Node *Ty;
{
SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
- Ty = parseType();
+ Ty = getDerived().parseType();
}
if (Ty == nullptr)
if (consumeIf('_')) {
size_t ExprsBegin = Names.size();
while (!consumeIf('E')) {
- Node *E = parseExpr();
+ Node *E = getDerived().parseExpr();
if (E == nullptr)
return E;
Names.push_back(E);
return make<ConversionExpr>(Ty, Exprs);
}
- Node *E[1] = {parseExpr()};
+ Node *E[1] = {getDerived().parseExpr()};
if (E[0] == nullptr)
return nullptr;
return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
// ::= L <mangled-name> E # external name
-template<typename Alloc> Node *Db<Alloc>::parseExprPrimary() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
if (!consumeIf('L'))
return nullptr;
switch (look()) {
case 'w':
++First;
- return parseIntegerLiteral("wchar_t");
+ return getDerived().parseIntegerLiteral("wchar_t");
case 'b':
if (consumeIf("b0E"))
return make<BoolExpr>(0);
return nullptr;
case 'c':
++First;
- return parseIntegerLiteral("char");
+ return getDerived().parseIntegerLiteral("char");
case 'a':
++First;
- return parseIntegerLiteral("signed char");
+ return getDerived().parseIntegerLiteral("signed char");
case 'h':
++First;
- return parseIntegerLiteral("unsigned char");
+ return getDerived().parseIntegerLiteral("unsigned char");
case 's':
++First;
- return parseIntegerLiteral("short");
+ return getDerived().parseIntegerLiteral("short");
case 't':
++First;
- return parseIntegerLiteral("unsigned short");
+ return getDerived().parseIntegerLiteral("unsigned short");
case 'i':
++First;
- return parseIntegerLiteral("");
+ return getDerived().parseIntegerLiteral("");
case 'j':
++First;
- return parseIntegerLiteral("u");
+ return getDerived().parseIntegerLiteral("u");
case 'l':
++First;
- return parseIntegerLiteral("l");
+ return getDerived().parseIntegerLiteral("l");
case 'm':
++First;
- return parseIntegerLiteral("ul");
+ return getDerived().parseIntegerLiteral("ul");
case 'x':
++First;
- return parseIntegerLiteral("ll");
+ return getDerived().parseIntegerLiteral("ll");
case 'y':
++First;
- return parseIntegerLiteral("ull");
+ return getDerived().parseIntegerLiteral("ull");
case 'n':
++First;
- return parseIntegerLiteral("__int128");
+ return getDerived().parseIntegerLiteral("__int128");
case 'o':
++First;
- return parseIntegerLiteral("unsigned __int128");
+ return getDerived().parseIntegerLiteral("unsigned __int128");
case 'f':
++First;
- return parseFloatingLiteral<float>();
+ return getDerived().template parseFloatingLiteral<float>();
case 'd':
++First;
- return parseFloatingLiteral<double>();
+ return getDerived().template parseFloatingLiteral<double>();
case 'e':
++First;
- return parseFloatingLiteral<long double>();
+ return getDerived().template parseFloatingLiteral<long double>();
case '_':
if (consumeIf("_Z")) {
- Node *R = parseEncoding();
+ Node *R = getDerived().parseEncoding();
if (R != nullptr && consumeIf('E'))
return R;
}
return nullptr;
default: {
// might be named type
- Node *T = parseType();
+ Node *T = getDerived().parseType();
if (T == nullptr)
return nullptr;
StringView N = parseNumber();
// ::= di <field source-name> <braced-expression> # .name = expr
// ::= dx <index expression> <braced-expression> # [expr] = expr
// ::= dX <range begin expression> <range end expression> <braced-expression>
-template<typename Alloc> Node *Db<Alloc>::parseBracedExpr() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
if (look() == 'd') {
switch (look(1)) {
case 'i': {
First += 2;
- Node *Field = parseSourceName(/*NameState=*/nullptr);
+ Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
if (Field == nullptr)
return nullptr;
- Node *Init = parseBracedExpr();
+ Node *Init = getDerived().parseBracedExpr();
if (Init == nullptr)
return nullptr;
return make<BracedExpr>(Field, Init, /*isArray=*/false);
}
case 'x': {
First += 2;
- Node *Index = parseExpr();
+ Node *Index = getDerived().parseExpr();
if (Index == nullptr)
return nullptr;
- Node *Init = parseBracedExpr();
+ Node *Init = getDerived().parseBracedExpr();
if (Init == nullptr)
return nullptr;
return make<BracedExpr>(Index, Init, /*isArray=*/true);
}
case 'X': {
First += 2;
- Node *RangeBegin = parseExpr();
+ Node *RangeBegin = getDerived().parseExpr();
if (RangeBegin == nullptr)
return nullptr;
- Node *RangeEnd = parseExpr();
+ Node *RangeEnd = getDerived().parseExpr();
if (RangeEnd == nullptr)
return nullptr;
- Node *Init = parseBracedExpr();
+ Node *Init = getDerived().parseBracedExpr();
if (Init == nullptr)
return nullptr;
return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
}
}
}
- return parseExpr();
+ return getDerived().parseExpr();
}
// (not yet in the spec)
// ::= fR <binary-operator-name> <expression> <expression>
// ::= fl <binary-operator-name> <expression>
// ::= fr <binary-operator-name> <expression>
-template<typename Alloc> Node *Db<Alloc>::parseFoldExpr() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
if (!consumeIf('f'))
return nullptr;
else if (consumeIf("rS")) OperatorName = ">>=";
else return nullptr;
- Node *Pack = parseExpr(), *Init = nullptr;
+ Node *Pack = getDerived().parseExpr(), *Init = nullptr;
if (Pack == nullptr)
return nullptr;
if (HasInitializer) {
- Init = parseExpr();
+ Init = getDerived().parseExpr();
if (Init == nullptr)
return nullptr;
}
// ::= fl <binary-operator-name> <expression>
// ::= fr <binary-operator-name> <expression>
// ::= <expr-primary>
-template<typename Alloc> Node *Db<Alloc>::parseExpr() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
bool Global = consumeIf("gs");
if (numLeft() < 2)
return nullptr;
switch (*First) {
case 'L':
- return parseExprPrimary();
+ return getDerived().parseExprPrimary();
case 'T':
- return parseTemplateParam();
+ return getDerived().parseTemplateParam();
case 'f': {
// Disambiguate a fold expression from a <function-param>.
if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
- return parseFunctionParam();
- return parseFoldExpr();
+ return getDerived().parseFunctionParam();
+ return getDerived().parseFoldExpr();
}
case 'a':
switch (First[1]) {
case 'a':
First += 2;
- return parseBinaryExpr("&&");
+ return getDerived().parseBinaryExpr("&&");
case 'd':
First += 2;
- return parsePrefixExpr("&");
+ return getDerived().parsePrefixExpr("&");
case 'n':
First += 2;
- return parseBinaryExpr("&");
+ return getDerived().parseBinaryExpr("&");
case 'N':
First += 2;
- return parseBinaryExpr("&=");
+ return getDerived().parseBinaryExpr("&=");
case 'S':
First += 2;
- return parseBinaryExpr("=");
+ return getDerived().parseBinaryExpr("=");
case 't': {
First += 2;
- Node *Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (Ty == nullptr)
return nullptr;
return make<EnclosingExpr>("alignof (", Ty, ")");
}
case 'z': {
First += 2;
- Node *Ty = parseExpr();
+ Node *Ty = getDerived().parseExpr();
if (Ty == nullptr)
return nullptr;
return make<EnclosingExpr>("alignof (", Ty, ")");
// cc <type> <expression> # const_cast<type>(expression)
case 'c': {
First += 2;
- Node *Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (Ty == nullptr)
return Ty;
- Node *Ex = parseExpr();
+ Node *Ex = getDerived().parseExpr();
if (Ex == nullptr)
return Ex;
return make<CastExpr>("const_cast", Ty, Ex);
// cl <expression>+ E # call
case 'l': {
First += 2;
- Node *Callee = parseExpr();
+ Node *Callee = getDerived().parseExpr();
if (Callee == nullptr)
return Callee;
size_t ExprsBegin = Names.size();
while (!consumeIf('E')) {
- Node *E = parseExpr();
+ Node *E = getDerived().parseExpr();
if (E == nullptr)
return E;
Names.push_back(E);
}
case 'm':
First += 2;
- return parseBinaryExpr(",");
+ return getDerived().parseBinaryExpr(",");
case 'o':
First += 2;
- return parsePrefixExpr("~");
+ return getDerived().parsePrefixExpr("~");
case 'v':
- return parseConversionExpr();
+ return getDerived().parseConversionExpr();
}
return nullptr;
case 'd':
switch (First[1]) {
case 'a': {
First += 2;
- Node *Ex = parseExpr();
+ Node *Ex = getDerived().parseExpr();
if (Ex == nullptr)
return Ex;
return make<DeleteExpr>(Ex, Global, /*is_array=*/true);
}
case 'c': {
First += 2;
- Node *T = parseType();
+ Node *T = getDerived().parseType();
if (T == nullptr)
return T;
- Node *Ex = parseExpr();
+ Node *Ex = getDerived().parseExpr();
if (Ex == nullptr)
return Ex;
return make<CastExpr>("dynamic_cast", T, Ex);
}
case 'e':
First += 2;
- return parsePrefixExpr("*");
+ return getDerived().parsePrefixExpr("*");
case 'l': {
First += 2;
- Node *E = parseExpr();
+ Node *E = getDerived().parseExpr();
if (E == nullptr)
return E;
return make<DeleteExpr>(E, Global, /*is_array=*/false);
}
case 'n':
- return parseUnresolvedName();
+ return getDerived().parseUnresolvedName();
case 's': {
First += 2;
- Node *LHS = parseExpr();
+ Node *LHS = getDerived().parseExpr();
if (LHS == nullptr)
return nullptr;
- Node *RHS = parseExpr();
+ Node *RHS = getDerived().parseExpr();
if (RHS == nullptr)
return nullptr;
return make<MemberExpr>(LHS, ".*", RHS);
}
case 't': {
First += 2;
- Node *LHS = parseExpr();
+ Node *LHS = getDerived().parseExpr();
if (LHS == nullptr)
return LHS;
- Node *RHS = parseExpr();
+ Node *RHS = getDerived().parseExpr();
if (RHS == nullptr)
return nullptr;
return make<MemberExpr>(LHS, ".", RHS);
}
case 'v':
First += 2;
- return parseBinaryExpr("/");
+ return getDerived().parseBinaryExpr("/");
case 'V':
First += 2;
- return parseBinaryExpr("/=");
+ return getDerived().parseBinaryExpr("/=");
}
return nullptr;
case 'e':
switch (First[1]) {
case 'o':
First += 2;
- return parseBinaryExpr("^");
+ return getDerived().parseBinaryExpr("^");
case 'O':
First += 2;
- return parseBinaryExpr("^=");
+ return getDerived().parseBinaryExpr("^=");
case 'q':
First += 2;
- return parseBinaryExpr("==");
+ return getDerived().parseBinaryExpr("==");
}
return nullptr;
case 'g':
switch (First[1]) {
case 'e':
First += 2;
- return parseBinaryExpr(">=");
+ return getDerived().parseBinaryExpr(">=");
case 't':
First += 2;
- return parseBinaryExpr(">");
+ return getDerived().parseBinaryExpr(">");
}
return nullptr;
case 'i':
switch (First[1]) {
case 'x': {
First += 2;
- Node *Base = parseExpr();
+ Node *Base = getDerived().parseExpr();
if (Base == nullptr)
return nullptr;
- Node *Index = parseExpr();
+ Node *Index = getDerived().parseExpr();
if (Index == nullptr)
return Index;
return make<ArraySubscriptExpr>(Base, Index);
First += 2;
size_t InitsBegin = Names.size();
while (!consumeIf('E')) {
- Node *E = parseBracedExpr();
+ Node *E = getDerived().parseBracedExpr();
if (E == nullptr)
return nullptr;
Names.push_back(E);
switch (First[1]) {
case 'e':
First += 2;
- return parseBinaryExpr("<=");
+ return getDerived().parseBinaryExpr("<=");
case 's':
First += 2;
- return parseBinaryExpr("<<");
+ return getDerived().parseBinaryExpr("<<");
case 'S':
First += 2;
- return parseBinaryExpr("<<=");
+ return getDerived().parseBinaryExpr("<<=");
case 't':
First += 2;
- return parseBinaryExpr("<");
+ return getDerived().parseBinaryExpr("<");
}
return nullptr;
case 'm':
switch (First[1]) {
case 'i':
First += 2;
- return parseBinaryExpr("-");
+ return getDerived().parseBinaryExpr("-");
case 'I':
First += 2;
- return parseBinaryExpr("-=");
+ return getDerived().parseBinaryExpr("-=");
case 'l':
First += 2;
- return parseBinaryExpr("*");
+ return getDerived().parseBinaryExpr("*");
case 'L':
First += 2;
- return parseBinaryExpr("*=");
+ return getDerived().parseBinaryExpr("*=");
case 'm':
First += 2;
if (consumeIf('_'))
- return parsePrefixExpr("--");
- Node *Ex = parseExpr();
+ return getDerived().parsePrefixExpr("--");
+ Node *Ex = getDerived().parseExpr();
if (Ex == nullptr)
return nullptr;
return make<PostfixExpr>(Ex, "--");
switch (First[1]) {
case 'a':
case 'w':
- return parseNewExpr();
+ return getDerived().parseNewExpr();
case 'e':
First += 2;
- return parseBinaryExpr("!=");
+ return getDerived().parseBinaryExpr("!=");
case 'g':
First += 2;
- return parsePrefixExpr("-");
+ return getDerived().parsePrefixExpr("-");
case 't':
First += 2;
- return parsePrefixExpr("!");
+ return getDerived().parsePrefixExpr("!");
case 'x':
First += 2;
- Node *Ex = parseExpr();
+ Node *Ex = getDerived().parseExpr();
if (Ex == nullptr)
return Ex;
return make<EnclosingExpr>("noexcept (", Ex, ")");
case 'o':
switch (First[1]) {
case 'n':
- return parseUnresolvedName();
+ return getDerived().parseUnresolvedName();
case 'o':
First += 2;
- return parseBinaryExpr("||");
+ return getDerived().parseBinaryExpr("||");
case 'r':
First += 2;
- return parseBinaryExpr("|");
+ return getDerived().parseBinaryExpr("|");
case 'R':
First += 2;
- return parseBinaryExpr("|=");
+ return getDerived().parseBinaryExpr("|=");
}
return nullptr;
case 'p':
switch (First[1]) {
case 'm':
First += 2;
- return parseBinaryExpr("->*");
+ return getDerived().parseBinaryExpr("->*");
case 'l':
First += 2;
- return parseBinaryExpr("+");
+ return getDerived().parseBinaryExpr("+");
case 'L':
First += 2;
- return parseBinaryExpr("+=");
+ return getDerived().parseBinaryExpr("+=");
case 'p': {
First += 2;
if (consumeIf('_'))
- return parsePrefixExpr("++");
- Node *Ex = parseExpr();
+ return getDerived().parsePrefixExpr("++");
+ Node *Ex = getDerived().parseExpr();
if (Ex == nullptr)
return Ex;
return make<PostfixExpr>(Ex, "++");
}
case 's':
First += 2;
- return parsePrefixExpr("+");
+ return getDerived().parsePrefixExpr("+");
case 't': {
First += 2;
- Node *L = parseExpr();
+ Node *L = getDerived().parseExpr();
if (L == nullptr)
return nullptr;
- Node *R = parseExpr();
+ Node *R = getDerived().parseExpr();
if (R == nullptr)
return nullptr;
return make<MemberExpr>(L, "->", R);
case 'q':
if (First[1] == 'u') {
First += 2;
- Node *Cond = parseExpr();
+ Node *Cond = getDerived().parseExpr();
if (Cond == nullptr)
return nullptr;
- Node *LHS = parseExpr();
+ Node *LHS = getDerived().parseExpr();
if (LHS == nullptr)
return nullptr;
- Node *RHS = parseExpr();
+ Node *RHS = getDerived().parseExpr();
if (RHS == nullptr)
return nullptr;
return make<ConditionalExpr>(Cond, LHS, RHS);
switch (First[1]) {
case 'c': {
First += 2;
- Node *T = parseType();
+ Node *T = getDerived().parseType();
if (T == nullptr)
return T;
- Node *Ex = parseExpr();
+ Node *Ex = getDerived().parseExpr();
if (Ex == nullptr)
return Ex;
return make<CastExpr>("reinterpret_cast", T, Ex);
}
case 'm':
First += 2;
- return parseBinaryExpr("%");
+ return getDerived().parseBinaryExpr("%");
case 'M':
First += 2;
- return parseBinaryExpr("%=");
+ return getDerived().parseBinaryExpr("%=");
case 's':
First += 2;
- return parseBinaryExpr(">>");
+ return getDerived().parseBinaryExpr(">>");
case 'S':
First += 2;
- return parseBinaryExpr(">>=");
+ return getDerived().parseBinaryExpr(">>=");
}
return nullptr;
case 's':
switch (First[1]) {
case 'c': {
First += 2;
- Node *T = parseType();
+ Node *T = getDerived().parseType();
if (T == nullptr)
return T;
- Node *Ex = parseExpr();
+ Node *Ex = getDerived().parseExpr();
if (Ex == nullptr)
return Ex;
return make<CastExpr>("static_cast", T, Ex);
}
case 'p': {
First += 2;
- Node *Child = parseExpr();
+ Node *Child = getDerived().parseExpr();
if (Child == nullptr)
return nullptr;
return make<ParameterPackExpansion>(Child);
}
case 'r':
- return parseUnresolvedName();
+ return getDerived().parseUnresolvedName();
case 't': {
First += 2;
- Node *Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (Ty == nullptr)
return Ty;
return make<EnclosingExpr>("sizeof (", Ty, ")");
}
case 'z': {
First += 2;
- Node *Ex = parseExpr();
+ Node *Ex = getDerived().parseExpr();
if (Ex == nullptr)
return Ex;
return make<EnclosingExpr>("sizeof (", Ex, ")");
case 'Z':
First += 2;
if (look() == 'T') {
- Node *R = parseTemplateParam();
+ Node *R = getDerived().parseTemplateParam();
if (R == nullptr)
return nullptr;
return make<SizeofParamPackExpr>(R);
} else if (look() == 'f') {
- Node *FP = parseFunctionParam();
+ Node *FP = getDerived().parseFunctionParam();
if (FP == nullptr)
return nullptr;
return make<EnclosingExpr>("sizeof... (", FP, ")");
First += 2;
size_t ArgsBegin = Names.size();
while (!consumeIf('E')) {
- Node *Arg = parseTemplateArg();
+ Node *Arg = getDerived().parseTemplateArg();
if (Arg == nullptr)
return nullptr;
Names.push_back(Arg);
switch (First[1]) {
case 'e': {
First += 2;
- Node *Ex = parseExpr();
+ Node *Ex = getDerived().parseExpr();
if (Ex == nullptr)
return Ex;
return make<EnclosingExpr>("typeid (", Ex, ")");
}
case 'i': {
First += 2;
- Node *Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (Ty == nullptr)
return Ty;
return make<EnclosingExpr>("typeid (", Ty, ")");
}
case 'l': {
First += 2;
- Node *Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (Ty == nullptr)
return nullptr;
size_t InitsBegin = Names.size();
while (!consumeIf('E')) {
- Node *E = parseBracedExpr();
+ Node *E = getDerived().parseBracedExpr();
if (E == nullptr)
return nullptr;
Names.push_back(E);
return make<NameType>("throw");
case 'w': {
First += 2;
- Node *Ex = parseExpr();
+ Node *Ex = getDerived().parseExpr();
if (Ex == nullptr)
return nullptr;
return make<ThrowExpr>(Ex);
case '7':
case '8':
case '9':
- return parseUnresolvedName();
+ return getDerived().parseUnresolvedName();
}
return nullptr;
}
//
// <v-offset> ::= <offset number> _ <virtual offset number>
// # virtual base override, with vcall offset
-template<typename Alloc> bool Db<Alloc>::parseCallOffset() {
+template <typename Alloc, typename Derived>
+bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
// Just scan through the call offset, we never add this information into the
// output.
if (consumeIf('h'))
// ::= GR <object name> <seq-id> _ # Subsequent temporaries
// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
// extension ::= GR <object name> # reference temporary for object
-template<typename Alloc> Node *Db<Alloc>::parseSpecialName() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
switch (look()) {
case 'T':
switch (look(1)) {
// TV <type> # virtual table
case 'V': {
First += 2;
- Node *Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (Ty == nullptr)
return nullptr;
return make<SpecialName>("vtable for ", Ty);
// TT <type> # VTT structure (construction vtable index)
case 'T': {
First += 2;
- Node *Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (Ty == nullptr)
return nullptr;
return make<SpecialName>("VTT for ", Ty);
// TI <type> # typeinfo structure
case 'I': {
First += 2;
- Node *Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (Ty == nullptr)
return nullptr;
return make<SpecialName>("typeinfo for ", Ty);
// TS <type> # typeinfo name (null-terminated byte string)
case 'S': {
First += 2;
- Node *Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (Ty == nullptr)
return nullptr;
return make<SpecialName>("typeinfo name for ", Ty);
First += 2;
if (parseCallOffset() || parseCallOffset())
return nullptr;
- Node *Encoding = parseEncoding();
+ Node *Encoding = getDerived().parseEncoding();
if (Encoding == nullptr)
return nullptr;
return make<SpecialName>("covariant return thunk to ", Encoding);
// # construction vtable for second-in-first
case 'C': {
First += 2;
- Node *FirstType = parseType();
+ Node *FirstType = getDerived().parseType();
if (FirstType == nullptr)
return nullptr;
if (parseNumber(true).empty() || !consumeIf('_'))
return nullptr;
- Node *SecondType = parseType();
+ Node *SecondType = getDerived().parseType();
if (SecondType == nullptr)
return nullptr;
return make<CtorVtableSpecialName>(SecondType, FirstType);
// TW <object name> # Thread-local wrapper
case 'W': {
First += 2;
- Node *Name = parseName();
+ Node *Name = getDerived().parseName();
if (Name == nullptr)
return nullptr;
return make<SpecialName>("thread-local wrapper routine for ", Name);
// TH <object name> # Thread-local initialization
case 'H': {
First += 2;
- Node *Name = parseName();
+ Node *Name = getDerived().parseName();
if (Name == nullptr)
return nullptr;
return make<SpecialName>("thread-local initialization routine for ", Name);
bool IsVirt = look() == 'v';
if (parseCallOffset())
return nullptr;
- Node *BaseEncoding = parseEncoding();
+ Node *BaseEncoding = getDerived().parseEncoding();
if (BaseEncoding == nullptr)
return nullptr;
if (IsVirt)
// GV <object name> # Guard variable for one-time initialization
case 'V': {
First += 2;
- Node *Name = parseName();
+ Node *Name = getDerived().parseName();
if (Name == nullptr)
return nullptr;
return make<SpecialName>("guard variable for ", Name);
// GR <object name> <seq-id> _ # Subsequent temporaries
case 'R': {
First += 2;
- Node *Name = parseName();
+ Node *Name = getDerived().parseName();
if (Name == nullptr)
return nullptr;
size_t Count;
// <encoding> ::= <function name> <bare-function-type>
// ::= <data name>
// ::= <special-name>
-template<typename Alloc> Node *Db<Alloc>::parseEncoding() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
if (look() == 'G' || look() == 'T')
- return parseSpecialName();
+ return getDerived().parseSpecialName();
auto IsEndOfEncoding = [&] {
// The set of chars that can potentially follow an <encoding> (none of which
};
NameState NameInfo(this);
- Node *Name = parseName(&NameInfo);
+ Node *Name = getDerived().parseName(&NameInfo);
if (Name == nullptr)
return nullptr;
if (consumeIf("Ua9enable_ifI")) {
size_t BeforeArgs = Names.size();
while (!consumeIf('E')) {
- Node *Arg = parseTemplateArg();
+ Node *Arg = getDerived().parseTemplateArg();
if (Arg == nullptr)
return nullptr;
Names.push_back(Arg);
Node *ReturnType = nullptr;
if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
- ReturnType = parseType();
+ ReturnType = getDerived().parseType();
if (ReturnType == nullptr)
return nullptr;
}
size_t ParamsBegin = Names.size();
do {
- Node *Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (Ty == nullptr)
return nullptr;
Names.push_back(Ty);
static constexpr const char *spec = "%LaL";
};
-template<typename Alloc>
-template<class Float>
-Node *Db<Alloc>::parseFloatingLiteral() {
+template <typename Alloc, typename Derived>
+template <class Float>
+Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
const size_t N = FloatData<Float>::mangled_size;
if (numLeft() <= N)
return nullptr;
}
// <seq-id> ::= <0-9A-Z>+
-template<typename Alloc> bool Db<Alloc>::parseSeqId(size_t *Out) {
+template <typename Alloc, typename Derived>
+bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
if (!(look() >= '0' && look() <= '9') &&
!(look() >= 'A' && look() <= 'Z'))
return true;
// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
-template<typename Alloc> Node *Db<Alloc>::parseSubstitution() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
if (!consumeIf('S'))
return nullptr;
// Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
// has ABI tags, the tags are appended to the substitution; the result is a
// substitutable component.
- Node *WithTags = parseAbiTags(SpecialSub);
+ Node *WithTags = getDerived().parseAbiTags(SpecialSub);
if (WithTags != SpecialSub) {
Subs.push_back(WithTags);
SpecialSub = WithTags;
// <template-param> ::= T_ # first template parameter
// ::= T <parameter-2 non-negative number> _
-template<typename Alloc> Node *Db<Alloc>::parseTemplateParam() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
if (!consumeIf('T'))
return nullptr;
// ::= <expr-primary> # simple expressions
// ::= J <template-arg>* E # argument pack
// ::= LZ <encoding> E # extension
-template<typename Alloc> Node *Db<Alloc>::parseTemplateArg() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
switch (look()) {
case 'X': {
++First;
- Node *Arg = parseExpr();
+ Node *Arg = getDerived().parseExpr();
if (Arg == nullptr || !consumeIf('E'))
return nullptr;
return Arg;
++First;
size_t ArgsBegin = Names.size();
while (!consumeIf('E')) {
- Node *Arg = parseTemplateArg();
+ Node *Arg = getDerived().parseTemplateArg();
if (Arg == nullptr)
return nullptr;
Names.push_back(Arg);
// ::= LZ <encoding> E # extension
if (look(1) == 'Z') {
First += 2;
- Node *Arg = parseEncoding();
+ Node *Arg = getDerived().parseEncoding();
if (Arg == nullptr || !consumeIf('E'))
return nullptr;
return Arg;
}
// ::= <expr-primary> # simple expressions
- return parseExprPrimary();
+ return getDerived().parseExprPrimary();
}
default:
- return parseType();
+ return getDerived().parseType();
}
}
// <template-args> ::= I <template-arg>* E
// extension, the abi says <template-arg>+
-template <typename Alloc>
-Node *Db<Alloc>::parseTemplateArgs(bool TagTemplates) {
+template <typename Derived, typename Alloc>
+Node *
+AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
if (!consumeIf('I'))
return nullptr;
while (!consumeIf('E')) {
if (TagTemplates) {
auto OldParams = std::move(TemplateParams);
- Node *Arg = parseTemplateArg();
+ Node *Arg = getDerived().parseTemplateArg();
TemplateParams = std::move(OldParams);
if (Arg == nullptr)
return nullptr;
}
TemplateParams.push_back(TableEntry);
} else {
- Node *Arg = parseTemplateArg();
+ Node *Arg = getDerived().parseTemplateArg();
if (Arg == nullptr)
return nullptr;
Names.push_back(Arg);
// extension ::= ___Z <encoding> _block_invoke
// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
-template<typename Alloc> Node *Db<Alloc>::parse() {
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parse() {
if (consumeIf("_Z")) {
- Node *Encoding = parseEncoding();
+ Node *Encoding = getDerived().parseEncoding();
if (Encoding == nullptr)
return nullptr;
if (look() == '.') {
}
if (consumeIf("___Z")) {
- Node *Encoding = parseEncoding();
+ Node *Encoding = getDerived().parseEncoding();
if (Encoding == nullptr || !consumeIf("_block_invoke"))
return nullptr;
bool RequireNumber = consumeIf('_');
return make<SpecialName>("invocation function for block in ", Encoding);
}
- Node *Ty = parseType();
+ Node *Ty = getDerived().parseType();
if (numLeft() != 0)
return nullptr;
return Ty;
}
+template <typename Alloc>
+struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
+ using AbstractManglingParser<ManglingParser<Alloc>,
+ Alloc>::AbstractManglingParser;
+};
+
} // namespace itanium_demangle
} // namespace llvm