}
};
+class DefaultAllocator {
+ BumpPointerAllocator Alloc;
+
+public:
+ void reset() { Alloc.reset(); }
+
+ template<typename T, typename ...Args> T *makeNode(Args &&...args) {
+ return new (Alloc.allocate(sizeof(T)))
+ T(std::forward<Args>(args)...);
+ }
+
+ void *allocateNodeArray(size_t sz) {
+ return Alloc.allocate(sizeof(Node *) * sz);
+ }
+};
+
+template<typename Alloc = DefaultAllocator>
struct Db {
const char *First;
const char *Last;
bool PermitForwardTemplateReferences = false;
bool ParsingLambdaParams = false;
- BumpPointerAllocator ASTAllocator;
+ Alloc ASTAllocator;
Db(const char *First_, const char *Last_) : First(First_), Last(Last_) {}
}
template <class T, class... Args> T *make(Args &&... args) {
- return new (ASTAllocator.allocate(sizeof(T)))
- T(std::forward<Args>(args)...);
+ return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
}
template <class It> NodeArray makeNodeArray(It begin, It end) {
size_t sz = static_cast<size_t>(end - begin);
- void *mem = ASTAllocator.allocate(sizeof(Node *) * sz);
+ void *mem = ASTAllocator.allocateNodeArray(sz);
Node **data = new (mem) Node *[sz];
std::copy(begin, end, data);
return NodeArray(data, sz);
//
// <unscoped-template-name> ::= <unscoped-name>
// ::= <substitution>
-Node *Db::parseName(NameState *State) {
+template<typename Alloc> Node *Db<Alloc>::parseName(NameState *State) {
consumeIf('L'); // extension
if (look() == 'N')
// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
// := Z <function encoding> E s [<discriminator>]
// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
-Node *Db::parseLocalName(NameState *State) {
+template<typename Alloc> Node *Db<Alloc>::parseLocalName(NameState *State) {
if (!consumeIf('Z'))
return nullptr;
Node *Encoding = parseEncoding();
// <unscoped-name> ::= <unqualified-name>
// ::= St <unqualified-name> # ::std::
// extension ::= StL<unqualified-name>
-Node *Db::parseUnscopedName(NameState *State) {
+template<typename Alloc> Node *Db<Alloc>::parseUnscopedName(NameState *State) {
if (consumeIf("StL") || consumeIf("St")) {
Node *R = parseUnqualifiedName(State);
if (R == nullptr)
// ::= <source-name>
// ::= <unnamed-type-name>
// ::= DC <source-name>+ E # structured binding declaration
-Node *Db::parseUnqualifiedName(NameState *State) {
- // <ctor-dtor-name>s are special-cased in parseNestedName().
- Node *Result;
- if (look() == 'U')
- Result = parseUnnamedTypeName(State);
- else if (look() >= '1' && look() <= '9')
- Result = parseSourceName(State);
- else if (consumeIf("DC")) {
- size_t BindingsBegin = Names.size();
- do {
- Node *Binding = parseSourceName(State);
- if (Binding == nullptr)
- return nullptr;
- Names.push_back(Binding);
- } while (!consumeIf('E'));
- Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
- } else
- Result = parseOperatorName(State);
- if (Result != nullptr)
- Result = parseAbiTags(Result);
- return Result;
+template<typename Alloc>
+Node *Db<Alloc>::parseUnqualifiedName(NameState *State) {
+ // <ctor-dtor-name>s are special-cased in parseNestedName().
+ Node *Result;
+ if (look() == 'U')
+ Result = parseUnnamedTypeName(State);
+ else if (look() >= '1' && look() <= '9')
+ Result = parseSourceName(State);
+ else if (consumeIf("DC")) {
+ size_t BindingsBegin = Names.size();
+ do {
+ Node *Binding = parseSourceName(State);
+ if (Binding == nullptr)
+ return nullptr;
+ Names.push_back(Binding);
+ } while (!consumeIf('E'));
+ Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
+ } else
+ Result = parseOperatorName(State);
+ if (Result != nullptr)
+ Result = parseAbiTags(Result);
+ return Result;
}
// <unnamed-type-name> ::= Ut [<nonnegative number>] _
// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
//
// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
-Node *Db::parseUnnamedTypeName(NameState *) {
+template<typename Alloc> Node *Db<Alloc>::parseUnnamedTypeName(NameState *) {
if (consumeIf("Ut")) {
StringView Count = parseNumber();
if (!consumeIf('_'))
}
// <source-name> ::= <positive length number> <identifier>
-Node *Db::parseSourceName(NameState *) {
+template<typename Alloc> Node *Db<Alloc>::parseSourceName(NameState *) {
size_t Length = 0;
if (parsePositiveInteger(&Length))
return nullptr;
// ::= rS # >>=
// ::= ss # <=> C++2a
// ::= v <digit> <source-name> # vendor extended operator
-Node *Db::parseOperatorName(NameState *State) {
+template<typename Alloc> Node *Db<Alloc>::parseOperatorName(NameState *State) {
switch (look()) {
case 'a':
switch (look(1)) {
// ::= D1 # complete object destructor
// ::= D2 # base object destructor
// extension ::= D5 # ?
-Node *Db::parseCtorDtorName(Node *&SoFar, NameState *State) {
+template<typename Alloc>
+Node *Db<Alloc>::parseCtorDtorName(Node *&SoFar, NameState *State) {
if (SoFar->K == Node::KSpecialSubstitution) {
auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
switch (SSK) {
// <template-prefix> ::= <prefix> <template unqualified-name>
// ::= <template-param>
// ::= <substitution>
-Node *Db::parseNestedName(NameState *State) {
+template<typename Alloc> Node *Db<Alloc>::parseNestedName(NameState *State) {
if (!consumeIf('N'))
return nullptr;
}
// <simple-id> ::= <source-name> [ <template-args> ]
-Node *Db::parseSimpleId() {
+template<typename Alloc> Node *Db<Alloc>::parseSimpleId() {
Node *SN = parseSourceName(/*NameState=*/nullptr);
if (SN == nullptr)
return nullptr;
// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
// ::= <simple-id> # e.g., ~A<2*N>
-Node *Db::parseDestructorName() {
+template<typename Alloc> Node *Db<Alloc>::parseDestructorName() {
Node *Result;
if (std::isdigit(look()))
Result = parseSimpleId();
// <unresolved-type> ::= <template-param>
// ::= <decltype>
// ::= <substitution>
-Node *Db::parseUnresolvedType() {
+template<typename Alloc> Node *Db<Alloc>::parseUnresolvedType() {
if (look() == 'T') {
Node *TP = parseTemplateParam();
if (TP == nullptr)
// ::= on <operator-name> <template-args> # unresolved operator template-id
// ::= dn <destructor-name> # destructor or pseudo-destructor;
// # e.g. ~X or ~X<N-1>
-Node *Db::parseBaseUnresolvedName() {
+template<typename Alloc> Node *Db<Alloc>::parseBaseUnresolvedName() {
if (std::isdigit(look()))
return parseSimpleId();
// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
//
// <unresolved-qualifier-level> ::= <simple-id>
-Node *Db::parseUnresolvedName() {
+template<typename Alloc> Node *Db<Alloc>::parseUnresolvedName() {
Node *SoFar = nullptr;
// srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
// <abi-tags> ::= <abi-tag> [<abi-tags>]
// <abi-tag> ::= B <source-name>
-Node *Db::parseAbiTags(Node *N) {
+template<typename Alloc> Node *Db<Alloc>::parseAbiTags(Node *N) {
while (consumeIf('B')) {
StringView SN = parseBareSourceName();
if (SN.empty())
}
// <number> ::= [n] <non-negative decimal integer>
-StringView Db::parseNumber(bool AllowNegative) {
+template<typename Alloc>
+StringView Db<Alloc>::parseNumber(bool AllowNegative) {
const char *Tmp = First;
if (AllowNegative)
consumeIf('n');
}
// <positive length number> ::= [0-9]*
-bool Db::parsePositiveInteger(size_t *Out) {
+template<typename Alloc> bool Db<Alloc>::parsePositiveInteger(size_t *Out) {
*Out = 0;
if (look() < '0' || look() > '9')
return true;
return false;
}
-StringView Db::parseBareSourceName() {
+template<typename Alloc> StringView Db<Alloc>::parseBareSourceName() {
size_t Int = 0;
if (parsePositiveInteger(&Int) || numLeft() < Int)
return StringView();
//
// <ref-qualifier> ::= R # & ref-qualifier
// <ref-qualifier> ::= O # && ref-qualifier
-Node *Db::parseFunctionType() {
+template<typename Alloc> Node *Db<Alloc>::parseFunctionType() {
Qualifiers CVQuals = parseCVQualifiers();
Node *ExceptionSpec = nullptr;
// ::= Dv [<dimension expression>] _ <element type>
// <extended element type> ::= <element type>
// ::= p # AltiVec vector pixel
-Node *Db::parseVectorType() {
+template<typename Alloc> Node *Db<Alloc>::parseVectorType() {
if (!consumeIf("Dv"))
return nullptr;
if (look() >= '1' && look() <= '9') {
// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
// ::= DT <expression> E # decltype of an expression (C++0x)
-Node *Db::parseDecltype() {
+template<typename Alloc> Node *Db<Alloc>::parseDecltype() {
if (!consumeIf('D'))
return nullptr;
if (!consumeIf('t') && !consumeIf('T'))
// <array-type> ::= A <positive dimension number> _ <element type>
// ::= A [<dimension expression>] _ <element type>
-Node *Db::parseArrayType() {
+template<typename Alloc> Node *Db<Alloc>::parseArrayType() {
if (!consumeIf('A'))
return nullptr;
}
// <pointer-to-member-type> ::= M <class type> <member type>
-Node *Db::parsePointerToMemberType() {
+template<typename Alloc> Node *Db<Alloc>::parsePointerToMemberType() {
if (!consumeIf('M'))
return nullptr;
Node *ClassType = parseType();
// ::= 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'
-Node *Db::parseClassEnumType() {
+template<typename Alloc> Node *Db<Alloc>::parseClassEnumType() {
StringView ElabSpef;
if (consumeIf("Ts"))
ElabSpef = "struct";
// <qualified-type> ::= <qualifiers> <type>
// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
-Node *Db::parseQualifiedType() {
+template<typename Alloc> Node *Db<Alloc>::parseQualifiedType() {
if (consumeIf('U')) {
StringView Qual = parseBareSourceName();
if (Qual.empty())
//
// <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>
-Node *Db::parseType() {
+template<typename Alloc> Node *Db<Alloc>::parseType() {
Node *Result = nullptr;
if (TypeCallback != nullptr)
return Result;
}
-Node *Db::parsePrefixExpr(StringView Kind) {
+template<typename Alloc> Node *Db<Alloc>::parsePrefixExpr(StringView Kind) {
Node *E = parseExpr();
if (E == nullptr)
return nullptr;
return make<PrefixExpr>(Kind, E);
}
-Node *Db::parseBinaryExpr(StringView Kind) {
+template<typename Alloc> Node *Db<Alloc>::parseBinaryExpr(StringView Kind) {
Node *LHS = parseExpr();
if (LHS == nullptr)
return nullptr;
return make<BinaryExpr>(LHS, Kind, RHS);
}
-Node *Db::parseIntegerLiteral(StringView Lit) {
+template<typename Alloc> Node *Db<Alloc>::parseIntegerLiteral(StringView Lit) {
StringView Tmp = parseNumber(true);
if (!Tmp.empty() && consumeIf('E'))
return make<IntegerExpr>(Lit, Tmp);
}
// <CV-Qualifiers> ::= [r] [V] [K]
-Qualifiers Db::parseCVQualifiers() {
+template<typename Alloc> Qualifiers Db<Alloc>::parseCVQualifiers() {
Qualifiers CVR = QualNone;
if (consumeIf('r'))
addQualifiers(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
-Node *Db::parseFunctionParam() {
+template<typename Alloc> Node *Db<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
-Node *Db::parseNewExpr() {
+template<typename Alloc> Node *Db<Alloc>::parseNewExpr() {
bool Global = consumeIf("gs");
bool IsArray = look(1) == 'a';
if (!consumeIf("nw") && !consumeIf("na"))
// cv <type> <expression> # conversion with one argument
// cv <type> _ <expression>* E # conversion with a different number of arguments
-Node *Db::parseConversionExpr() {
+template<typename Alloc> Node *Db<Alloc>::parseConversionExpr() {
if (!consumeIf("cv"))
return nullptr;
Node *Ty;
// ::= 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
-Node *Db::parseExprPrimary() {
+template<typename Alloc> Node *Db<Alloc>::parseExprPrimary() {
if (!consumeIf('L'))
return nullptr;
switch (look()) {
// ::= di <field source-name> <braced-expression> # .name = expr
// ::= dx <index expression> <braced-expression> # [expr] = expr
// ::= dX <range begin expression> <range end expression> <braced-expression>
-Node *Db::parseBracedExpr() {
+template<typename Alloc> Node *Db<Alloc>::parseBracedExpr() {
if (look() == 'd') {
switch (look(1)) {
case 'i': {
// ::= fR <binary-operator-name> <expression> <expression>
// ::= fl <binary-operator-name> <expression>
// ::= fr <binary-operator-name> <expression>
-Node *Db::parseFoldExpr() {
+template<typename Alloc> Node *Db<Alloc>::parseFoldExpr() {
if (!consumeIf('f'))
return nullptr;
// ::= fl <binary-operator-name> <expression>
// ::= fr <binary-operator-name> <expression>
// ::= <expr-primary>
-Node *Db::parseExpr() {
+template<typename Alloc> Node *Db<Alloc>::parseExpr() {
bool Global = consumeIf("gs");
if (numLeft() < 2)
return nullptr;
//
// <v-offset> ::= <offset number> _ <virtual offset number>
// # virtual base override, with vcall offset
-bool Db::parseCallOffset() {
+template<typename Alloc> bool Db<Alloc>::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
-Node *Db::parseSpecialName() {
+template<typename Alloc> Node *Db<Alloc>::parseSpecialName() {
switch (look()) {
case 'T':
switch (look(1)) {
// <encoding> ::= <function name> <bare-function-type>
// ::= <data name>
// ::= <special-name>
-Node *Db::parseEncoding() {
+template<typename Alloc> Node *Db<Alloc>::parseEncoding() {
if (look() == 'G' || look() == 'T')
return parseSpecialName();
constexpr const char *FloatData<long double>::spec;
-template <class Float> Node *Db::parseFloatingLiteral() {
+template<typename Alloc>
+template<class Float>
+Node *Db<Alloc>::parseFloatingLiteral() {
const size_t N = FloatData<Float>::mangled_size;
if (numLeft() <= N)
return nullptr;
}
// <seq-id> ::= <0-9A-Z>+
-bool Db::parseSeqId(size_t *Out) {
+template<typename Alloc> bool Db<Alloc>::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> >
-Node *Db::parseSubstitution() {
+template<typename Alloc> Node *Db<Alloc>::parseSubstitution() {
if (!consumeIf('S'))
return nullptr;
// <template-param> ::= T_ # first template parameter
// ::= T <parameter-2 non-negative number> _
-Node *Db::parseTemplateParam() {
+template<typename Alloc> Node *Db<Alloc>::parseTemplateParam() {
if (!consumeIf('T'))
return nullptr;
// ::= <expr-primary> # simple expressions
// ::= J <template-arg>* E # argument pack
// ::= LZ <encoding> E # extension
-Node *Db::parseTemplateArg() {
+template<typename Alloc> Node *Db<Alloc>::parseTemplateArg() {
switch (look()) {
case 'X': {
++First;
// <template-args> ::= I <template-arg>* E
// extension, the abi says <template-arg>+
-Node *Db::parseTemplateArgs(bool TagTemplates) {
+template <typename Alloc>
+Node *Db<Alloc>::parseTemplateArgs(bool TagTemplates) {
if (!consumeIf('I'))
return nullptr;
// extension ::= ___Z <encoding> _block_invoke
// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
-Node *Db::parse() {
+template<typename Alloc> Node *Db<Alloc>::parse() {
if (consumeIf("_Z")) {
Node *Encoding = parseEncoding();
if (Encoding == nullptr)
}
int InternalStatus = demangle_success;
- Db Parser(MangledName, MangledName + std::strlen(MangledName));
+ Db<> Parser(MangledName, MangledName + std::strlen(MangledName));
OutputStream S;
Node *AST = Parser.parse();
bool llvm::itaniumFindTypesInMangledName(const char *MangledName, void *Ctx,
void (*Callback)(void *,
const char *)) {
- Db Parser(MangledName, MangledName + std::strlen(MangledName));
+ Db<> Parser(MangledName, MangledName + std::strlen(MangledName));
Parser.TypeCallback = Callback;
Parser.TypeCallbackContext = Ctx;
return Parser.parse() == nullptr;
namespace llvm {
ItaniumPartialDemangler::ItaniumPartialDemangler()
- : RootNode(nullptr), Context(new Db{nullptr, nullptr}) {}
+ : RootNode(nullptr), Context(new Db<>{nullptr, nullptr}) {}
ItaniumPartialDemangler::~ItaniumPartialDemangler() {
- delete static_cast<Db *>(Context);
+ delete static_cast<Db<> *>(Context);
}
ItaniumPartialDemangler::ItaniumPartialDemangler(
// Demangle MangledName into an AST, storing it into this->RootNode.
bool ItaniumPartialDemangler::partialDemangle(const char *MangledName) {
- Db *Parser = static_cast<Db *>(Context);
+ Db<> *Parser = static_cast<Db<> *>(Context);
size_t Len = std::strlen(MangledName);
Parser->reset(MangledName, MangledName + Len);
RootNode = Parser->parse();
bool ItaniumPartialDemangler::isData() const {
return !isFunction() && !isSpecialName();
}
-}
+} // namespace llvm